http服务器长连接的实现

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <process.h>
  4. #include <winsock2.h>
  5. #pragma comment(lib,"ws2_32")
  6. #define I_GET               0x00000001
  7. #define I_POST              0x00000002
  8. typedef struct web_socket
  9. {
  10.     SOCKET socket;
  11.     struct sockaddr_in client_in;
  12.     WSAEVENT event;
  13.     char *buffer;
  14.     u_long length;
  15.     char *data;             //post数据
  16.     u_long ul_datalength;   //post长度
  17.     
  18.     char *httppath;         //请求路径
  19.     char *pathparam;    //请求路径后面的参数
  20.     int  i_method;          //提交方式
  21.     bool b_isConnect;       //长连接
  22. }web_socket;
  23. unsigned __stdcall thread_client_web(void*);
  24. int main(int argc, char* argv[])
  25. {
  26.     WSADATA WSAData;
  27.     WSAStartup(MAKEWORD(2,2),&WSAData);
  28.     struct sockaddr_in server_in;
  29.     SOCKET sock;
  30.     server_in.sin_family = AF_INET;
  31.     server_in.sin_port = htons(99);
  32.     server_in.sin_addr.s_addr = INADDR_ANY;
  33.     sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  34.     bind(sock,(struct sockaddr far*)&server_in,sizeof(server_in));
  35.     listen(sock,10);
  36.     while(true)
  37.     {
  38.         web_socket *web = (web_socket*)malloc(sizeof(web_socket));
  39.         memset(web,0x0,sizeof(web_socket));
  40.         int c_len = sizeof(web->client_in);
  41.         web->socket = accept(sock,(struct sockaddr far*)&web->client_in,&c_len);
  42.         
  43.         _beginthreadex(NULL,0,thread_client_web,web,0,NULL);
  44.     }
  45.     printf("Hello World!/n");
  46.     WSACleanup();
  47.     return 0;
  48. }
  49. char * __stdcall _thread_client_recv_find_header_key_to_string(char *header,char *key,char *outval)
  50. {
  51.     char *find,*find_over;
  52.     find = strstr(header,key);
  53.     if(find == NULL || (find_over = strstr(find,"/r/n")) == NULL )
  54.         return NULL;
  55.     else
  56.     {
  57.         find+=strlen(key);
  58.         find++;
  59.         memcpy(outval,find,find_over-find);
  60.         return outval;
  61.     }
  62. }
  63. bool __stdcall _thread_client_recv_find_header_key_bool(char *header,char *key,char *val)
  64. {
  65.     char outval[32]={0};
  66.     if(_thread_client_recv_find_header_key_to_string(header,key,outval)==NULL)
  67.         return false;
  68.     else
  69.     {
  70.         if(strstr(outval,val) != NULL)
  71.             return true;
  72.         else
  73.             return false;
  74.     }
  75. }
  76. int __stdcall _thread_client_recv_find_header_key_to_integer(char *header,char *key)
  77. {
  78.     char val[32]={0};
  79.     if(_thread_client_recv_find_header_key_to_string(header,key,val)==NULL)
  80.         return 0;
  81.     else
  82.         return atoi(val);
  83. }
  84. bool __stdcall _thread_client_recv_post_http_header(web_socket *web)
  85. {
  86.     char *t_find=NULL;
  87.     if(memcmp(web->buffer,"GET",3)==0)
  88.     {
  89.         web->i_method = I_GET;
  90.         web->httppath = strstr(web->buffer,"GET ");
  91.         web->httppath+=strlen("GET ");
  92.     }
  93.     else if(memcmp(web->buffer,"POST",4)==0)
  94.     {
  95.         web->i_method = I_POST;
  96.         web->httppath = strstr(web->buffer,"POST ");
  97.         web->httppath+=strlen("POST ");
  98.         web->data+=2;
  99.         *web->data = '/0';
  100.         web->data = web->data+2;
  101.         web->ul_datalength = _thread_client_recv_find_header_key_to_integer(web->buffer,"Content-Length");
  102.     }
  103.     
  104.     web->b_isConnect = _thread_client_recv_find_header_key_bool(web->buffer,"Connection","keep-alive");
  105.     if(web->httppath == NULL)
  106.         return false;
  107.     t_find = strstr(web->httppath," ");
  108.     if(t_find != NULL)
  109.     {
  110.         *t_find = '/0';
  111.     }
  112.     t_find = strstr(web->httppath,"?");
  113.     if(t_find != NULL)
  114.     {
  115.         *t_find = '/0';
  116.         web->pathparam = t_find+1;
  117.     }
  118.     return true;
  119. }
  120. bool __stdcall _thread_client_check_is_recv(web_socket *web)
  121. {
  122.     if(web->i_method == 0 )
  123.     {
  124.         web->data = strstr(web->buffer,"/r/n/r/n");
  125.         if(NULL == web->data)
  126.             return true;
  127.         else
  128.             _thread_client_recv_post_http_header(web);
  129.     }
  130.     if(web->i_method == I_GET)
  131.     {
  132.         return false;
  133.     }
  134.     else if(web->i_method == I_POST)
  135.     {
  136.         if(web->ul_datalength == strlen(web->data))
  137.             return false;
  138.     }
  139.     return true;
  140. }
  141. unsigned __stdcall thread_client_web_send(web_socket *web)
  142. {
  143.     if(web->i_method == I_GET)
  144.         printf("RECV:%d/n%s:%s/n",web->length,web->httppath,web->pathparam);
  145.     else if(web->i_method == I_POST)
  146.         printf("RECV:%d/n%s:%s/n%s/n",web->length,web->httppath,web->pathparam,web->data);
  147.     char t[]="aaaaa";
  148.     char buff[512]={0};
  149.     sprintf(buff,"http/1.0 200 ok/r/nContent-Length:%d/r/nConnection:Keep-Alive/r/n/r/n%s",strlen(t),t);
  150.     send(web->socket,buff,strlen(buff),0);
  151.     return 1;
  152. }
  153. unsigned __stdcall thread_client_web(void* param)
  154. {
  155. #define PAGE_SIZE 0x2000
  156.     
  157.     bool isRecvOver;
  158.     web_socket *web = (web_socket*)param;
  159.     web->event = WSACreateEvent();
  160.     web->buffer = (char*)malloc(PAGE_SIZE*10);
  161.     
  162.     WSAEventSelect(web->socket,web->event,FD_READ|FD_CLOSE);
  163.     WSANETWORKEVENTS networkevent;
  164.     u_long cRecv;
  165. web_loop_next:
  166.     isRecvOver=true;
  167.     
  168.     memset(web->buffer,0x0,PAGE_SIZE*10);
  169.     web->length=0;
  170.     web->b_isConnect = true;
  171.     web->i_method=0;
  172.     web->data=NULL;
  173.     web->httppath=NULL;
  174.     web->pathparam=NULL;
  175.     while(isRecvOver)
  176.     {
  177.         WaitForSingleObject(web->event,INFINITE);
  178.     
  179.         WSAEnumNetworkEvents(web->socket,web->event,&networkevent);
  180.         if(networkevent.lNetworkEvents & FD_READ)
  181.         {
  182.             ioctlsocket(web->socket,FIONREAD,&cRecv);
  183.             web->length += recv(web->socket,web->buffer+web->length,cRecv,0);
  184.             isRecvOver = _thread_client_check_is_recv(web);
  185.         }
  186.         else if(networkevent.lNetworkEvents & FD_CLOSE)
  187.         {
  188.             closesocket(web->socket);
  189.             isRecvOver=false;
  190.             web->b_isConnect=false;
  191.             goto _exit;
  192.         }
  193.     }
  194.     thread_client_web_send(web);
  195. //  if(web->b_isConnect)
  196.         goto web_loop_next;
  197.     
  198. _exit:
  199.     printf("over");
  200.     
  201.     free(web->buffer);
  202.     free(web);
  203.     return 0;
  204. }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值