socket堵塞的解决方法

来源:互联网 发布:mama投票软件 编辑:程序博客网 时间:2024/06/02 17:22

进行网络开发会出现堵塞的情况,一般来说,会有三种解决办法:

  1. 在头部约定好数据的长度。当读取到的长度等于这个长度时就不再继续调用recv方法
  2. 约定结束标志,当读到该结束标志时退出不再recv
  3. 设置超时,会在设置的超时时间到达后退出而不再阻塞

第一种方法简单实用,但是如果返回头信息中是transfer-encoding:chunked,即分块传输的情况无法使用;
第二种方法碰到比较复杂的返回不好处理;
第三种可以,但是对网络的要求比较高。

对于分块传输的情况则不能通过Content-Length:xx来获取报文长度,我是通过设置超时来解决的,代码如下:

while(1)    {        FD_ZERO(&rfds);//清空描述符集合         FD_SET(0, &rfds);//将标准输入(stdin)添加到集合中        FD_SET(socket_fd, &rfds);//将我们的套接字描述符添加到集合中        /*设置超时时间*/        timeout.tv_sec = 1;           timeout.tv_usec = 0;        /*监听套接字是否超时*/        if(select(socket_fd+1, &rfds, NULL, NULL, &timeout) <= 0)break;        memset(lpbuf2,0,BUFFER_SIZE);        bytes_received = recv(socket_fd, lpbuf2, BUFFER_SIZE, 0);        /*获取网络字节*/        if(bytes_received > 0)        {            strncpy(res,lpbuf2,bytes_received);            sprintf(response + strlen(response),"%s",res);        }    }

获取的字符串是如下的形式:
head: headdata\r\n ………头信息
\r\n
len1\r\n ….分块传输的第一块的长度
body1\r\n …..分块传输的第一块
len2\r\n …..分块传输的第二块的长度
body2\r\n …..分块传输的第二块
…\r\n ……………分块传输的第n块的长度和第n块
0\r\n ………..结束符
\r\n

可以发现,约定了结束标志\r\n0\r\n,可以使用第三种方法,感兴趣的可以自己试试,然后是对获取的如上形式的字符串解析,获取body1body2这样形式的真正的内容。
代码如下:

char *http_parse_result(const char*lpbuf){    char *ptmp = NULL;     static char response[16384] = "";    int len;    char chunkedbody[16384] = "";    ptmp = (char*)strstr(lpbuf,"HTTP/1.1");    if(!ptmp){        printf("http/1.1 not faind\n");        return NULL;    }    if(atoi(ptmp + 9)!=200){        printf("result:\n%s\n",lpbuf);        return NULL;    }    ptmp = (char*)strstr(lpbuf,"\r\n\r\n");//\r\n\r\n1fbd\r\nbody\r\n1223\r\nbody\r\n0\r\n\r\n    if(!ptmp){        printf("ptmp is NULL\n");        return NULL;    }    ptmp = ptmp + 4;//1fbd\r\nbody\r\n1223\r\nbody\r\n0\r\n\r\n    printf("ptmp=%s\n",ptmp);    while(*ptmp != '\0')    {        len = strtol(ptmp,NULL,16);        if(len == 0)        {            response[strlen(response)] = '\0';            break;        }        printf("len=%d\n",len);        ptmp = (char*)strstr(ptmp,"\r\n");//\r\nbody1\r\n1223\r\nbody2\r\n0\r\n\r\n        strncpy(chunkedbody,ptmp + 2,len);        printf("chunkedbody=%s\n",chunkedbody);        sprintf(response+strlen(response),"%s",chunkedbody);        memset(chunkedbody,0,16384);        ptmp = ptmp + len + 4;//1223\r\nbody2\r\n0\r\n\r\n    }    return response;}

就这样,有一点需要注意的是获取的网络字节是unicode形式的,需要先编码再解析。

原创粉丝点击