调用recv()/如何接收分块压缩数据后出现总线错误

时间:2012-01-21 09:17:51

标签: c sockets tcp tcpclient

您好我有一个简单的浏览器向yahoo.com发送请求,服务器响应告诉我200 Ok并且它将使用encoded-transfer发送gzip文件:chunked。这很好,但是当我运行我的程序并不断调用recv()时,我最终遇到了Bus Error。我不确定这意味着什么。此外,我不清楚如何读取数据包的标头,告诉我它将发送多少字节,因为压缩文件是在机器代码中。在这个问题中,我包含了正确的代码以及我在终端中看到的输出。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

#define MAXDATASIZE 500;

int main(int argc, char *argv[]){
struct addrinfo serverSide,*serverInfo;
int mySock, status;
char buf[501],ipstr[INET6_ADDRSTRLEN];

memset(&serverSide, 0, sizeof serverSide);
serverSide.ai_family = AF_UNSPEC;
serverSide.ai_socktype = SOCK_STREAM;

if(getaddrinfo("www.yahoo.com","80",&serverSide,&serverInfo)==0){

}

mySock = socket(serverInfo->ai_family, serverInfo->ai_socktype, serverInfo->ai_protocol);
connect(mySock, serverInfo->ai_addr, serverInfo->ai_addrlen);

char msg[500] = "GET http://www.yahoo.com HTTP/1.1\r\n";
strcat(msg,"Host: www.yahoo.com:80\r\n");
strcat(msg,"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1\r\n");
strcat(msg,"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n");
strcat(msg,"Accept-Language: en-us,en;q=0.5\r\n");
strcat(msg,"Accept-Encoding: gzip, deflate\r\n");
strcat(msg,"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n");
strcat(msg,"Connection: keep-alive\r\n\r\n");

// I want to keep the code simple so I just call recv enough times to see what has been
// written to my buffer. If I could read the packet length in the header then I would 
// code in a while loop to adjust for that.
if((status = send(mySock,msg,strlen(msg),0))== -1){
printf("request not sent %d\n",status);
perror("\n");
}else{
if((status = recv(mySock, buf, 1500, 0))== -1){
printf("recieved byte error");
}else{
printf("%s",buf);
}
if((status = recv(mySock, buf, 1500, 0))== -1){
printf("recieved byte error");
}else{
printf("%s",buf);
}
if((status = recv(mySock, buf, 1500, 0))== -1){
printf("recieved byte error");
}else{
printf("%s",buf);
}
if((status = recv(mySock, buf, 1500, 0))== -1){
printf("recieved byte error");
}else{
printf("%s",buf);
}
}
close(mySock);
freeaddrinfo(serverInfo);
return 0;
}

Bellow是我代码的输出。服务器响应以下内容......

  

HTTP / 1.1 200 OK日期:星期六,21一月2012 08:53:09 GMT Set-Cookie:   B = 4peq6lh7hkv7l和b = 3&安培; S = U4; expires = Tue,21-Jan-2014 20:00:00 GMT;   路径= /; domain = .yahoo.com P3P:   policyref =“http://info.yahoo.com/w3c/p3p.xml”,CP =“CAO DSP COR CUR ADM   DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi我们的DELi SAMi OTRi UNRi PUBi   IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV“   缓存控制:私有X-Frame选项:SAMEORIGIN Set-Cookie:   IU =删除; expires =星期五,2011年1月21日08:53:09 GMT;路径= /;   domain = .yahoo.com Set-Cookie:PH =已删除;到期= 2011年1月21日星期五   格林尼治标准时间08:53:09;路径= /; domain = .yahoo.com Set-Cookie:   FPC = d = 2BrdHmSMUw00.1uwnK1w8hHJcKnQt3UjRGxvUnBVIn0e6eAyRyd96eAPIN33Jne3IWoEE8r8eAk9xF0ExLsN5JJJmANZRlEBg8hpcDJ1GD7Gd50uZeP1H0_Wbf_mc.LJ45tDfhhwjR1BSedjT7AeGszK321i_gS34xKNuHlH2niKnP1lFG8y3aztEQsOkQHUu1w3zxk-&安培; V = 2;   expires = Sun,20-Jan-2013 08:53:10 GMT;路径= /;域= www.yahoo.com   Set-Cookie:CH =已删除; expires =星期五,2011年1月21日08:53:09 GMT;路径= /;   domain = www.yahoo.com Set-Cookie:   CH = AgBPGnwQAA9AEAAA3RAAKY0QAAMPEAAYcxAAKN0QAD5XEAASNBAAJeoQACI8;   expires =周一,20-Feb-2012 08:53:09 GMT;路径= /;域= .yahoo.com   设置Cookie:   FPT = d = nZFZlZHXecyEB3UWO0p6uOQtHkIdLjY734kqWOMHwg8Yq1e0sUpJBiMgYN63uaJ0.zEBsZIbeO93bfF0mXfQ8CtJYxAuet8CIS5PYmNMWfBDUU6ew8pXSI6cY3aX7Nk743wzRxbuCoBZGqvOM0eGhQMFOQ7BrCYBAZsAIYAOqwHKu7sNvbkPN7r0T7ncKpu5bX8LWPGngHHS97cCbNgpbgzOh13nP1m6.9cw7oPeudXdRjfzxsDUYqq2LvQJdECPWmccPhDEYfAoIl.Cfc8T8w_5.zrvoWG5kJr_T0megV4GtcTB324ZS2zkf0pi1GiMGYVHxGNh01c04XJnjk5q0ek_Xgogaa5oZoyhkMYQLI66nMCt1yAiz1jXmq2MTBxHqtbxBkoJaVsJt0YQMdpkkxwpRpXZHUgur.K9kY4j3vgyG1j44CQPlNsh7mBMxNe5nLdCMjFMy0ufmocRYowg38kMiK9hpFqkFnwYZSZPMGM4wAK5wVvFrwn1phkY3OXr76z5OC5tjNeq3Q - &安培; V = 1;   路径= /; domain = www.yahoo.com Set-Cookie:fpps =已删除;期满=星期五,   21-Jan-2011 08:53:09 GMT;路径= /; domain = www.yahoo.com Set-Cookie:   fpc_s = d = 33OMFTGMUw2Z.oeMhzS8DGMizJ2NFSc4VT5QjW6pM.25xOqOYy5nr_kK5C83.tjkxzIiFvBITPc7P5YBehviyRS3piAAliJxvHQHDlbZYOlAdvgPXzJ4zGghf.xEL6Rb6rVdP90xlOc_njpBqlqOcwyMeq0ZqBy2VXuNrIxiD9QjUUsJyfVJ4miF1frSXQOI5Z8MVIErFoBjW3jTQANFu_CayJrjp6RRDc.YG5DCn04SFk3hKALdzVPSyIoawxmicCoWFfN7dvyge8jRoeQXHey.IALpAtcCPlY4eX.teLb.GO0yQxUN5HzgR9I-&安培; V = 2;   路径= /; domain = www.yahoo.com变化:接受编码内容类型:   text / html; charset = utf-8 Content-Encoding:gzip年龄:2   Transfer-Encoding:chunked连接:keep-alive服务器:YTS / 1.20.0

     <00>000088e I HG8Ae��t�>#%xc�c#���a��e9��*d��S��@�~}�ZF��~x� 6�S8�#ӉO�i:i%��?���a��9rxJ�n���<Q����_�-�A����!D{�{ޱN���f*/h��ΰ ���Ea�h��E��2UY� 2�7�����dL>U���^W˳g��H�Q�>���~����iiΟ��@:���R�L�b��K���=�# Ғ�5���|'�J��eo { 巴士错误

2 个答案:

答案 0 :(得分:2)

char buf[501];
...
recv(mySock, buf, 1500, 0)
                  ^^^^

如果recv实际读取超过501个字节,则会溢出缓冲区,从而导致未定义的行为。确保从未读取超过501个字节,或增加缓冲区的大小。

printf也不安全。没有什么能保证输入正确,0 - 终止C字符串。 (您可以使用write并传递返回的recv长度。)

答案 1 :(得分:1)

乍一看,看起来你正在超越buf;你声明它的长度为501但是然后尝试读入1500个字节。