`
sogo6
  • 浏览: 110008 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

http服务器长连接的实现(C++)

阅读更多
#include <stdio.h> 
#include <stdlib.h> 
#include <process.h> 
#include <winsock2.h> 
#pragma comment(lib,"ws2_32") 

#define I_GET 0x00000001 
#define I_POST 0x00000002 

typedef struct web_socket 
{ 
SOCKET socket; 
struct sockaddr_in client_in; 
WSAEVENT event; 

char *buffer; 
u_long length; 

char *data; //post数据 
u_long ul_datalength; //post长度 

char *httppath; //请求路径 
char *pathparam; //请求路径后面的参数 

int i_method; //提交方式 
bool b_isConnect; //长连接 

}web_socket; 

unsigned __stdcall thread_client_web(void*); 

int main(int argc, char* argv[]) 
{ 
WSADATA WSAData; 
WSAStartup(MAKEWORD(2,2),&WSAData); 

struct sockaddr_in server_in; 
SOCKET sock; 

server_in.sin_family = AF_INET; 
server_in.sin_port = htons(99); 
server_in.sin_addr.s_addr = INADDR_ANY; 

sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
bind(sock,(struct sockaddr far*)&server_in,sizeof(server_in)); 

listen(sock,10); 

while(true) 
{ 
web_socket *web = (web_socket*)malloc(sizeof(web_socket)); 
memset(web,0x0,sizeof(web_socket)); 
int c_len = sizeof(web->client_in); 
web->socket = accept(sock,(struct sockaddr far*)&web->client_in,&c_len); 

_beginthreadex(NULL,0,thread_client_web,web,0,NULL); 

} 
printf("Hello World!\n"); 

WSACleanup(); 
return 0; 
} 

char * __stdcall _thread_client_recv_find_header_key_to_string(char *header,char *key,char *outval) 
{ 
char *find,*find_over; 
find = strstr(header,key); 
if(find == NULL || (find_over = strstr(find,"\r\n")) == NULL ) 
return NULL; 
else 
{ 
find+=strlen(key); 
find++; 
memcpy(outval,find,find_over-find); 
return outval; 
} 
} 

bool __stdcall _thread_client_recv_find_header_key_bool(char *header,char *key,char *val) 
{ 
char outval[32]={0}; 
if(_thread_client_recv_find_header_key_to_string(header,key,outval)==NULL) 
return false; 
else 
{ 
if(strstr(outval,val) != NULL) 
return true; 
else 
return false; 
} 
} 

int __stdcall _thread_client_recv_find_header_key_to_integer(char *header,char *key) 
{ 
char val[32]={0}; 
if(_thread_client_recv_find_header_key_to_string(header,key,val)==NULL) 
return 0; 
else 
return atoi(val); 
} 

bool __stdcall _thread_client_recv_post_http_header(web_socket *web) 
{ 
char *t_find=NULL; 
if(memcmp(web->buffer,"GET",3)==0) 
{ 
web->i_method = I_GET; 
web->httppath = strstr(web->buffer,"GET "); 
web->httppath+=strlen("GET "); 
} 
else if(memcmp(web->buffer,"POST",4)==0) 
{ 
web->i_method = I_POST; 
web->httppath = strstr(web->buffer,"POST "); 
web->httppath+=strlen("POST "); 

web->data+=2; 
*web->data = '\0'; 
web->data = web->data+2; 
web->ul_datalength = _thread_client_recv_find_header_key_to_integer(web->buffer,"Content-Length"); 
} 

web->b_isConnect = _thread_client_recv_find_header_key_bool(web->buffer,"Connection","keep-alive"); 

if(web->httppath == NULL) 
return false; 
t_find = strstr(web->httppath," "); 
if(t_find != NULL) 
{ 
*t_find = '\0'; 
} 
t_find = strstr(web->httppath,"?"); 
if(t_find != NULL) 
{ 
*t_find = '\0'; 
web->pathparam = t_find+1; 
} 
return true; 
} 

bool __stdcall _thread_client_check_is_recv(web_socket *web) 
{ 
if(web->i_method == 0 ) 
{ 
web->data = strstr(web->buffer,"\r\n\r\n"); 
if(NULL == web->data) 
return true; 
else 
_thread_client_recv_post_http_header(web); 
} 
if(web->i_method == I_GET) 
{ 
return false; 
} 
else if(web->i_method == I_POST) 
{ 
if(web->ul_datalength == strlen(web->data)) 
return false; 
} 
return true; 
} 

unsigned __stdcall thread_client_web_send(web_socket *web) 
{ 
if(web->i_method == I_GET) 
printf("RECV:%d\n%s:%s\n",web->length,web->httppath,web->pathparam); 
else if(web->i_method == I_POST) 
printf("RECV:%d\n%s:%s\n%s\n",web->length,web->httppath,web->pathparam,web->data); 
char t[]="aaaaa"; 
char buff[512]={0}; 

sprintf(buff,"http/1.0 200 ok\r\nContent-Length:%d\r\nConnection:Keep-Alive\r\n\r\n%s",strlen(t),t);

send(web->socket,buff,strlen(buff),0); 
return 1; 
} 

unsigned __stdcall thread_client_web(void* param) 
{ 
#define PAGE_SIZE 0x2000 

bool isRecvOver; 
web_socket *web = (web_socket*)param; 
web->event = WSACreateEvent(); 
web->buffer = (char*)malloc(PAGE_SIZE*10); 

WSAEventSelect(web->socket,web->event,FD_READ|FD_CLOSE); 

WSANETWORKEVENTS networkevent; 
u_long cRecv; 

web_loop_next: 
isRecvOver=true; 

memset(web->buffer,0x0,PAGE_SIZE*10); 
web->length=0; 
web->b_isConnect = true; 
web->i_method=0; 
web->data=NULL; 
web->httppath=NULL; 
web->pathparam=NULL; 

while(isRecvOver) 
{ 
WaitForSingleObject(web->event,INFINITE); 

WSAEnumNetworkEvents(web->socket,web->event,&networkevent); 
if(networkevent.lNetworkEvents & FD_READ) 
{ 
ioctlsocket(web->socket,FIONREAD,&cRecv); 
web->length += recv(web->socket,web->buffer+web->length,cRecv,0); 
isRecvOver = _thread_client_check_is_recv(web); 
} 
else if(networkevent.lNetworkEvents & FD_CLOSE) 
{ 
closesocket(web->socket); 
isRecvOver=false; 
web->b_isConnect=false; 
goto _exit; 
} 
} 

thread_client_web_send(web); 

// if(web->b_isConnect) 
goto web_loop_next; 

_exit: 
printf("over"); 

free(web->buffer); 
free(web); 
return 0; 
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics