用C模拟了一个http请求,但是recv函数接收的数据不完整且不安顺序获取信息

towaywu 2013-11-03 10:30:41
用C模拟了一个http请求,但是recv函数接收的数据不完整且不安顺序获取信息
我把代码贴上
#include <stdio.h>
#include "winsock2.h"
//#pragma comment(lib, "ws2_32.lib") //2.0版本
int main() {
// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( iResult != NO_ERROR ){
printf("Error at WSAStartup()\n");
}

// Create a socket.
SOCKET m_socket;
m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( m_socket == INVALID_SOCKET ) {
printf( "Error at socket(): %ld\n", WSAGetLastError() );
WSACleanup();
return 1;
}
// Connect to a server.
struct sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr("113.106.90.157");
clientService.sin_port = htons( 80 );
if ( connect( m_socket, (SOCKADDR*) &clientService, sizeof(SOCKADDR)) == SOCKET_ERROR){
printf( "Failed to connect.\n" );
WSACleanup();
return;
}

// Send and receive data.
int bytesSent;

char sendbuf[1024];
sprintf(sendbuf,"%s","GET / HTTP/1.1\r\n");
strcat(sendbuf,"Host: www.chachaoo.com\r\n");
strcat(sendbuf,"Content-Encoding: utf-8\r\n");
strcat(sendbuf,"User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0\r\n\r\n");

int bytesRecv = strlen(sendbuf);
char recvbuf[1024];
char *precvbuf = recvbuf;
bytesSent = send( m_socket, sendbuf, strlen(sendbuf), 0 );
printf( "Bytes Sent: %ld\n", bytesSent );

// bytesRecv = recv( m_socket, recvbuf, 2 , 0 );
// printf("\n %d\n",bytesRecv);


while( 1 ) {
bytesRecv = recv(m_socket, recvbuf,1024 , 0);
printf("%s",recvbuf);

// printf("\n%d\n",bytesRecv);
if(bytesRecv<=0){
break;
}

}



close(m_socket);
return 0;
}



...全文
675 56 打赏 收藏 转发到动态 举报
写回复
用AI写文章
56 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2013-11-06
  • 打赏
  • 举报
回复
引用 55 楼 towaywu 的回复:
各位这个已经弄明白了,主要还是中文乱码的原因,访问英文网站没问题,那个不明的字符串就不会出现了
对电脑而言没有乱码,只有二进制字节;对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A
towaywu 2013-11-05
  • 打赏
  • 举报
回复
引用 46 楼 pathletboy 的回复:
[quote=引用 44 楼 towaywu 的回复:]
你们说的都做了,还是出现

你#18的代码获取的html已经是正常的,出现的那个你认为是莫名的数字,#10帖子里的连接已经解释了,那个数字没有是不正常的,有才是正常的,他服务器端用chunked编码发,你只能按chunked编码解析,你控制不了人家服务器端,就好好的按照http协议进行规范通讯。[/quote]不是数字,是莫名其妙的字符串
pathletboy 2013-11-05
  • 打赏
  • 举报
回复
引用 44 楼 towaywu 的回复:
你们说的都做了,还是出现
你#18的代码获取的html已经是正常的,出现的那个你认为是莫名的数字,#10帖子里的连接已经解释了,那个数字没有是不正常的,有才是正常的,他服务器端用chunked编码发,你只能按chunked编码解析,你控制不了人家服务器端,就好好的按照http协议进行规范通讯。
pathletboy 2013-11-05
  • 打赏
  • 举报
回复
引用 44 楼 towaywu 的回复:
你们说的都做了,还是出现
出现什么,没明白你意思,我看你现在收到的完全正常的包。
towaywu 2013-11-05
  • 打赏
  • 举报
回复
你们说的都做了,还是出现
pathletboy 2013-11-05
  • 打赏
  • 举报
回复
引用 42 楼 zilaishuichina 的回复:
[quote=引用 39 楼 pathletboy 的回复:] [quote=引用 37 楼 towaywu 的回复:] [quote=引用 35 楼 zilaishuichina 的回复:]

while( 1 ) {
        memset(recvbuf, 0x00, sizeof(char)*1024);//加上这一行 你的输出就没有乱码的小尾巴了

        bytesRecv = recv(m_socket, recvbuf,1024 , 0);
        printf("%s",recvbuf);
      
       // printf("\n%d\n",bytesRecv);
        if(bytesRecv<=0){
            break;
        }     
        
    }
依然存在[/quote] 这代码2个问题都会导致输出乱码1、虽然1024字节是给清0了,如果收到1024长度的内容\0终止符还是没有了,只需要依据长度,长度+1的地方补个0就可以,不用清零1024字节,这样运行效率还高些。2、你收到的recv返回<=0你还是把内容输出了,那么把<=0的判断移动到输出前就可以。 按我这么改完就是我#1的代码。[/quote] 哦 写错了一个地方 memset(recvbuf, 0x00, sizeof(char)*1024);//加上这一行 你的输出就没有乱码的小尾巴了 bytesRecv = recv(m_socket, recvbuf,1023 , 0); 因为你是用tcp模拟的http 跟 你用tcp发送一段普通文本信息 没有任何区别 recvbuf是需要清0的 因为recv函数不会帮你清0 你的这些乱码的小尾巴 是因为: 比如你 第一次收到了 “GET / HTTP/1.1\r\n” 放在了recvbuf里面 第二次收到了 “Host: www.” 如果你没有清0 那么你第二次printf出来的就会变成 Host: www./1.1\r\n 当然你觉得memset效率低 可以简单一点处理
char sendbuf[1024];
bytesRecv = recv(m_socket, recvbuf,1023 , 0);
if (bytesRecv <= 0) 
    break;
recvbuf[bytesRecv] = '\0';
printf("%s",recvbuf);
[/quote] 还是错,收1023时候,1023字节被你0覆盖了,参照我#1吧。
towaywu 2013-11-05
  • 打赏
  • 举报
回复
各位这个已经弄明白了,主要还是中文乱码的原因,访问英文网站没问题,那个不明的字符串就不会出现了
zilaishuichina 2013-11-05
  • 打赏
  • 举报
回复
引用 39 楼 pathletboy 的回复:
[quote=引用 37 楼 towaywu 的回复:] [quote=引用 35 楼 zilaishuichina 的回复:]

while( 1 ) {
        memset(recvbuf, 0x00, sizeof(char)*1024);//加上这一行 你的输出就没有乱码的小尾巴了

        bytesRecv = recv(m_socket, recvbuf,1024 , 0);
        printf("%s",recvbuf);
      
       // printf("\n%d\n",bytesRecv);
        if(bytesRecv<=0){
            break;
        }     
        
    }
依然存在[/quote] 这代码2个问题都会导致输出乱码1、虽然1024字节是给清0了,如果收到1024长度的内容\0终止符还是没有了,只需要依据长度,长度+1的地方补个0就可以,不用清零1024字节,这样运行效率还高些。2、你收到的recv返回<=0你还是把内容输出了,那么把<=0的判断移动到输出前就可以。 按我这么改完就是我#1的代码。[/quote] 哦 写错了一个地方 memset(recvbuf, 0x00, sizeof(char)*1024);//加上这一行 你的输出就没有乱码的小尾巴了 bytesRecv = recv(m_socket, recvbuf,1023 , 0); 因为你是用tcp模拟的http 跟 你用tcp发送一段普通文本信息 没有任何区别 recvbuf是需要清0的 因为recv函数不会帮你清0 你的这些乱码的小尾巴 是因为: 比如你 第一次收到了 “GET / HTTP/1.1\r\n” 放在了recvbuf里面 第二次收到了 “Host: www.” 如果你没有清0 那么你第二次printf出来的就会变成 Host: www./1.1\r\n 当然你觉得memset效率低 可以简单一点处理
char sendbuf[1024];
bytesRecv = recv(m_socket, recvbuf,1023 , 0);
if (bytesRecv <= 0) 
    break;
recvbuf[bytesRecv] = '\0';
printf("%s",recvbuf);
赵4老师 2013-11-05
  • 打赏
  • 举报
回复
while( 1 ) {
    //bytesRecv = recv(m_socket, recvbuf,1024 , 0);
    //printf("%s",recvbuf);

   // printf("\n%d\n",bytesRecv);
   // if(bytesRecv<=0){
    //    break;
   // }
   bytesRecv = recv(m_socket, recvbuf,1024 , 0);
    if (bytesRecv <= 0) break;
//  recvbuf[bytesRecv+1] = 0;
//  printf("%s",recvbuf);
    HexDump(recvbuf,bytesRecv);
}


towaywu 2013-11-05
  • 打赏
  • 举报
回复
C刚弄,还得多向前辈们学习学习
赵4老师 2013-11-05
  • 打赏
  • 举报
回复
参考41楼。 recv收到的是字节数组,不是ASCIIZ串。
pathletboy 2013-11-05
  • 打赏
  • 举报
回复
引用 51 楼 zilaishuichina 的回复:
[quote=引用 43 楼 pathletboy 的回复:] [quote=引用 42 楼 zilaishuichina 的回复:] [quote=引用 39 楼 pathletboy 的回复:] [quote=引用 37 楼 towaywu 的回复:] [quote=引用 35 楼 zilaishuichina 的回复:]

while( 1 ) {
        memset(recvbuf, 0x00, sizeof(char)*1024);//加上这一行 你的输出就没有乱码的小尾巴了

        bytesRecv = recv(m_socket, recvbuf,1024 , 0);
        printf("%s",recvbuf);
      
       // printf("\n%d\n",bytesRecv);
        if(bytesRecv<=0){
            break;
        }     
        
    }
依然存在[/quote] 这代码2个问题都会导致输出乱码1、虽然1024字节是给清0了,如果收到1024长度的内容\0终止符还是没有了,只需要依据长度,长度+1的地方补个0就可以,不用清零1024字节,这样运行效率还高些。2、你收到的recv返回<=0你还是把内容输出了,那么把<=0的判断移动到输出前就可以。 按我这么改完就是我#1的代码。[/quote] 哦 写错了一个地方 memset(recvbuf, 0x00, sizeof(char)*1024);//加上这一行 你的输出就没有乱码的小尾巴了 bytesRecv = recv(m_socket, recvbuf,1023 , 0); 因为你是用tcp模拟的http 跟 你用tcp发送一段普通文本信息 没有任何区别 recvbuf是需要清0的 因为recv函数不会帮你清0 你的这些乱码的小尾巴 是因为: 比如你 第一次收到了 “GET / HTTP/1.1\r\n” 放在了recvbuf里面 第二次收到了 “Host: www.” 如果你没有清0 那么你第二次printf出来的就会变成 Host: www./1.1\r\n 当然你觉得memset效率低 可以简单一点处理
char sendbuf[1024];
bytesRecv = recv(m_socket, recvbuf,1023 , 0);
if (bytesRecv <= 0) 
    break;
recvbuf[bytesRecv] = '\0';
printf("%s",recvbuf);
[/quote] 还是错,收1023时候,1023字节被你0覆盖了,参照我#1吧。[/quote] 你那1楼的代码 才是不对的 recvbuf[bytesRecv+1] = 0; 这个+1是不需要的 收10个字节 那就是recvbuf[10] = 0; 应该是[/quote] 你是对的,楼主在我1楼代码上把recvbuf[bytesRecv+1]=0修改为recvbuf[bytesRecv]=0吧,当时想着收到后的末尾+1的字节给终止符,忽略了数组从0开始。
zilaishuichina 2013-11-05
  • 打赏
  • 举报
回复
引用 43 楼 pathletboy 的回复:
[quote=引用 42 楼 zilaishuichina 的回复:] [quote=引用 39 楼 pathletboy 的回复:] [quote=引用 37 楼 towaywu 的回复:] [quote=引用 35 楼 zilaishuichina 的回复:]

while( 1 ) {
        memset(recvbuf, 0x00, sizeof(char)*1024);//加上这一行 你的输出就没有乱码的小尾巴了

        bytesRecv = recv(m_socket, recvbuf,1024 , 0);
        printf("%s",recvbuf);
      
       // printf("\n%d\n",bytesRecv);
        if(bytesRecv<=0){
            break;
        }     
        
    }
依然存在[/quote] 这代码2个问题都会导致输出乱码1、虽然1024字节是给清0了,如果收到1024长度的内容\0终止符还是没有了,只需要依据长度,长度+1的地方补个0就可以,不用清零1024字节,这样运行效率还高些。2、你收到的recv返回<=0你还是把内容输出了,那么把<=0的判断移动到输出前就可以。 按我这么改完就是我#1的代码。[/quote] 哦 写错了一个地方 memset(recvbuf, 0x00, sizeof(char)*1024);//加上这一行 你的输出就没有乱码的小尾巴了 bytesRecv = recv(m_socket, recvbuf,1023 , 0); 因为你是用tcp模拟的http 跟 你用tcp发送一段普通文本信息 没有任何区别 recvbuf是需要清0的 因为recv函数不会帮你清0 你的这些乱码的小尾巴 是因为: 比如你 第一次收到了 “GET / HTTP/1.1\r\n” 放在了recvbuf里面 第二次收到了 “Host: www.” 如果你没有清0 那么你第二次printf出来的就会变成 Host: www./1.1\r\n 当然你觉得memset效率低 可以简单一点处理
char sendbuf[1024];
bytesRecv = recv(m_socket, recvbuf,1023 , 0);
if (bytesRecv <= 0) 
    break;
recvbuf[bytesRecv] = '\0';
printf("%s",recvbuf);
[/quote] 还是错,收1023时候,1023字节被你0覆盖了,参照我#1吧。[/quote] 你那1楼的代码 才是不对的 recvbuf[bytesRecv+1] = 0; 这个+1是不需要的 收10个字节 那就是recvbuf[10] = 0; 应该是
towaywu 2013-11-05
  • 打赏
  • 举报
回复
引用 49 楼 pathletboy 的回复:
[quote=引用 47 楼 towaywu 的回复:] [quote=引用 46 楼 pathletboy 的回复:] [quote=引用 44 楼 towaywu 的回复:] 你们说的都做了,还是出现
你#18的代码获取的html已经是正常的,出现的那个你认为是莫名的数字,#10帖子里的连接已经解释了,那个数字没有是不正常的,有才是正常的,他服务器端用chunked编码发,你只能按chunked编码解析,你控制不了人家服务器端,就好好的按照http协议进行规范通讯。[/quote]不是数字,是莫名其妙的字符串 [/quote] 图我再发一次,你再仔细看下。 [/quote] 好的,谢谢!我在研究研究
pathletboy 2013-11-05
  • 打赏
  • 举报
回复
引用 47 楼 towaywu 的回复:
[quote=引用 46 楼 pathletboy 的回复:]
[quote=引用 44 楼 towaywu 的回复:]
你们说的都做了,还是出现

你#18的代码获取的html已经是正常的,出现的那个你认为是莫名的数字,#10帖子里的连接已经解释了,那个数字没有是不正常的,有才是正常的,他服务器端用chunked编码发,你只能按chunked编码解析,你控制不了人家服务器端,就好好的按照http协议进行规范通讯。[/quote]不是数字,是莫名其妙的字符串
[/quote]
图我再发一次,你再仔细看下。
pathletboy 2013-11-05
  • 打赏
  • 举报
回复
引用 47 楼 towaywu 的回复:
[quote=引用 46 楼 pathletboy 的回复:] [quote=引用 44 楼 towaywu 的回复:] 你们说的都做了,还是出现
你#18的代码获取的html已经是正常的,出现的那个你认为是莫名的数字,#10帖子里的连接已经解释了,那个数字没有是不正常的,有才是正常的,他服务器端用chunked编码发,你只能按chunked编码解析,你控制不了人家服务器端,就好好的按照http协议进行规范通讯。[/quote]不是数字,是莫名其妙的字符串 [/quote] 26a 是16进制
max_min_ 2013-11-04
  • 打赏
  • 举报
回复
代码有bug, 抓包看看!看看发送的数据是否正确! 接受buf初始化下,另外检查接受数据的返回值!实际接收的数据的长度是多少!
s1mba 2013-11-04
  • 打赏
  • 举报
回复
引用 38 楼 Simba888888 的回复:
楼主看看我以前写的这篇文章 http://blog.csdn.net/jnu_simba/article/details/12352379
我觉得问题出在判断退出条件上吧,返回小于0的情况除非是-1表示出错了,可你既没有设置超时也没有被信号打断,所以不会返回-1吧?返回0表示对等方关闭连接了,但很难说对等方发完数据就会立马关闭连接,所以可能出现后面完整html之后还出现乱串。
pathletboy 2013-11-04
  • 打赏
  • 举报
回复
引用 37 楼 towaywu 的回复:
[quote=引用 35 楼 zilaishuichina 的回复:]

while( 1 ) {
        memset(recvbuf, 0x00, sizeof(char)*1024);//加上这一行 你的输出就没有乱码的小尾巴了

        bytesRecv = recv(m_socket, recvbuf,1024 , 0);
        printf("%s",recvbuf);
      
       // printf("\n%d\n",bytesRecv);
        if(bytesRecv<=0){
            break;
        }     
        
    }
依然存在[/quote] 这代码2个问题都会导致输出乱码1、虽然1024字节是给清0了,如果收到1024长度的内容\0终止符还是没有了,只需要依据长度,长度+1的地方补个0就可以,不用清零1024字节,这样运行效率还高些。2、你收到的recv返回<=0你还是把内容输出了,那么把<=0的判断移动到输出前就可以。 按我这么改完就是我#1的代码。
s1mba 2013-11-04
  • 打赏
  • 举报
回复
楼主看看我以前写的这篇文章 http://blog.csdn.net/jnu_simba/article/details/12352379
加载更多回复(36)

69,377

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧