首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

socket为何里面的recv一个字节一个字节读取 与 多个字节读取得到的结果为什么不正确

2012-10-23 
socket为什么里面的recv一个字节一个字节读取 与 多个字节读取得到的结果为什么不正确?C语言利用socket获

socket为什么里面的recv一个字节一个字节读取 与 多个字节读取得到的结果为什么不正确?
C语言利用socket获取网上资源时候 ,为什么里面的recv一个字节一个字节读取与多个字节读取得到的结构为什么不正确?有人能回答吗?在下面代码里面已经表明地方了就是 #1 和 #2 两个地方,希望对这方面比较了解的朋友能解答一下。

下面这段程序是通过socket来下载百度里面的图标图片,为什么recv单个字节接收能够接收到图片,而多个字节接收却报错呢,使用的编译器是windows平台下的MinGW,g++ 4.7

C/C++ code
/* * ===================================================================================== * *       Filename:  GetTheHtml.cpp * *    Description:  On Windows ,use the socket to get host's html or img * *        Version:  1.0 *        Created:  2012/10/9 19:25:52 *       Revision:  none *       Compiler:  gcc *         Author:  UnGeek *            Email:  ungeek5201314@gmail.com * * ===================================================================================== */#include <windows.h>#include <winsock2.h>#include <iostream>#include <string>#include <algorithm>#include <fstream>#include <string>#define BUFFSIZE 1024using namespace std;const int PORT = 80;const char  IP[]="220.181.111.148";const char RESOURCE[]="/img/baidu_sylogo1.gif";class initsock{    public:    initsock()    {        WSADATA wsadata;        if(WSAStartup(MAKEWORD(2,2),&wsadata))        {        }        else if(LOBYTE(wsadata.wVersion)!=2 ||                HIBYTE(wsadata.wVersion)!=2)        {        }    }    ~initsock()    {        WSACleanup();    }};int main(){    initsock s;        struct sockaddr_in server_addr;    /*init socket*/    int sockfd = socket(AF_INET, SOCK_STREAM, 0);    if (sockfd < 0) {        return -1;    }   // HOSTENT* web_host = gethostbyname("http://172.16.12.11");  //  printf("IP: %s\n", inet_ntoa(*((struct in_addr *)web_host->h_addr_list[0])));    memset(&server_addr, 0, sizeof(server_addr));    server_addr.sin_family    = AF_INET;    server_addr.sin_port    = htons(PORT);    server_addr.sin_addr.s_addr    = inet_addr(IP);//*((struct in_addr *)web_host->h_addr_list[0]);    int ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));    if (ret<0)    {        printf("error\n");    }    char request[BUFFSIZE];    memset(request, 0, sizeof(request));    sprintf(request,        "GET %s HTTP/1.1\r\n"        "Accept: */*\r\n"        "Accept-Language: zh-cn\r\n"        "User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n"        "Host: %s:%d\r\n"        "Connection: Close\r\n"        "\r\n",RESOURCE,IP,PORT);    ret = send(sockfd, request, sizeof(request), 0);    int  end, recvsize, count;    char recvbuf[BUFFSIZE];    fd_set read_fds;    struct timeval timeout;    /*建议时间要长点, select失败可能的原因是收到网站的响应消息超时*/    timeout.tv_sec  = 30;    timeout.tv_usec = 0;    FD_ZERO(&read_fds);    FD_SET(sockfd, &read_fds);    string str;    while (1) {        ret = select(sockfd+1, &read_fds, NULL, NULL, &timeout);        if (-1 == ret) {            /*出错,直接返回错误*/            fprintf(stderr, "select: %s\n", strerror(errno));            return -1;        }        else if (0 == ret) {            /*超时, 继续轮询*/            fprintf(stderr,"surpass\n");            break;        }        /*接受到数据*/        if (FD_ISSET(sockfd, &read_fds)) {            //问题出在这里//一个情况时单个字节读取,另一个是多个字节读取,为什么多个字节读取得到的图片是错误的呢            //^#1//            while (recv(sockfd, recvbuf,BUFFSIZE,0)) {////                str+=recvbuf;//            }//          break;            ////^#1            //^#2            while (recv(sockfd, recvbuf,1,0)==1)                {                    str+=recvbuf[0];                }            break;            ////$#2        }    }    FD_CLR(sockfd, &read_fds);    string::size_type pos = str.find("\r\n\r\n");    if(pos!=string::npos)    {        pos+=string("\r\n\r\n").length();    //    cout<<str.substr(pos);        fstream out("img.gif",ios::binary|ios::out);        out<<str.substr(pos);        out.close();    }    closesocket(sockfd);    return 0;} 



[解决办法]
string& operator+= ( const string& str );
string& operator+= ( const char* s );
string& operator+= ( char c );

参数需要常量字符串吧。
[解决办法]
str+=recvbuf;

recvbuf里面如果有'\0'的话,应该会被截断吧,然后str就不正确了。
[解决办法]
试试改成这样:
C/C++ code
int n = 0;            while (n = recv(sockfd, recvbuf,BUFFSIZE,0)) {                //str+=recvbuf;                str.append(recvbuf, n);            }
[解决办法]
图片数据是二进制的,非文本, 不要用string接收,改用std::vector<unsigned char>吧.另外,recv需要判读是否还有更多的数据.

热点排行