100分悬赏!!!在线等!!!

Zidane_2014 2014-07-31 08:20:39
今天写了一个SOCKET程序。
期望:向服务端(不用考虑实现)发起一个连接,并且向服务端发送一个XML文件,然后服务端返回一个XML文件。

大体上实现了上述功能。

重点来了
我接受到的XML文件总是少了一个字节
今天下午抓包看了,服务端传过来的数据是完整的。

我的代码:
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MYPORT 1029
#define BUFFERSIZE 1024

int main(int argc,char **argv)
{
if(argc!=2)
{
printf("argc<2\n");
exit(1);
}

struct sockaddr_in client_addr;
bzero(&client_addr,sizeof(client_addr));
client_addr.sin_family=AF_INET;
client_addr.sin_addr.s_addr=htons(INADDR_ANY);
client_addr.sin_port=htons(0);

int client_socket=socket(AF_INET,SOCK_STREAM,0);

if(client_socket<0)
{
printf("Create Socket Failed!\n");
exit(1);
}

if(bind(client_socket,(struct sockaddr *)&client_addr,sizeof(client_addr)))
{
printf("Client Bind Port Failed!\n");
exit(1);
}

struct sockaddr_in server_addr;
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
if(inet_aton(argv[1],&server_addr.sin_addr)==0)
{
printf("Server IP Address Error!\n");
exit(1);
}

server_addr.sin_port=htons(MYPORT);
socklen_t server_addr_length=sizeof(server_addr);

if(connect(client_socket,(struct sockaddr *)&server_addr,server_addr_length)<0)
{
printf("Can Not Connect To %s!\n",argv[1]);
exit(1);
}

char buf[BUFFERSIZE];



FILE *fp_1=fopen("send.xml","r");
if(fp_1==NULL)
{
printf("File not found!\n");
}
else
{
bzero(buf,BUFFERSIZE);
int file_block_length=0;
while((file_block_length=fread(buf,sizeof(char),BUFFERSIZE,fp_1))>0)
{
printf("flie_block_length=%d\n",file_block_length);
if(send(client_socket,buf,file_block_length,0)<0)
{
printf("Send file failed!\n");
break;
}
bzero(buf,sizeof(buf));
}
fclose(fp_1);
printf("Finished!\n");
}



FILE *fp=fopen("test.xml","w");
if(fp==NULL)
{
printf("Can Not Open To Write!\n");
exit(1);
}

bzero(buf,sizeof(buf));
int length=0;
while(length=recv(client_socket,buf,BUFFERSIZE,0))
{
if(length<0)
{
printf("Receive Data Failed!\n");
break;
}

int write_length=fwrite(buf,sizeof(char),length,fp);
if(write_length<length)
{
printf("Write Failed!\n");
break;
}
bzero(buf,BUFFERSIZE);
}
printf("Success!\n");
fclose(fp);
close(client_socket);
return 0;
}


大家帮忙啊!!!
...全文
1007 83 打赏 收藏 转发到动态 举报
写回复
用AI写文章
83 条回复
切换为时间正序
请发表友善的回复…
发表回复
Zidane_2014 2014-08-02
  • 打赏
  • 举报
回复
引用 79 楼 sagittarius_520 的回复:
[quote=引用 77 楼 Zidane_2014 的回复:] [quote=引用 75 楼 sagittarius_520 的回复:] [quote=引用 74 楼 Zidane_2014 的回复:] [quote=引用 71 楼 sagittarius_520 的回复:] 最后一个字符不是EOF吗?读到最后一个字符的时候你的while()循环判断失败了直接跳出去了,while(length=recv(client_socket,buf,BUFFERSIZE,0))这里面的循环根本不会执行啊,所以才会导致少了一个字节。 你可以在while里面加一个判断试试,里面这句话应该不会输出的。
	
if (length == EOF)
	{
		printf("file end!\n");
	}
但是跳出了之后不应该继续后面的代码吗??顺序执行会打印“success”呀。但问题是卡在那里,不来也不去。[/quote] printf()后面的代码都没有执行吗?[/quote]请看70楼的调试图。第一张图指明了程序停止(不能说停止,可能说卡在那里更合适)的地方。[/quote] 我个人认为你这while循环的判断while(length=recv(client_socket,buf,BUFFERSIZE,0))有问题,recv读取到最后一个字节的时候返回值并不是0吧?而是1,因为读取最后一个字节的时候recv还是读取到了东西,读取的是'\0'这个描述符,所以所length的值不为0,while循环继续,那么也就会出现你所说的读取到了不可能出现的字符。可以试着在while循环里面对length进行一个判断,如果为0则跳出循环。这可能就是程序为什么会一直卡死在while循环里面。[/quote]恩!我今晚上试一试。
Zidane_2014 2014-08-02
  • 打赏
  • 举报
回复
引用 76 楼 lovesmiles 的回复:
看你的截图,数据全部收到了buff了吧。你是不是经常用ctrl^D来结束程序?
     int write_length=fwrite(buf,sizeof(char),length,fp);
        if(write_length<length)
        {
            printf("Write Failed!\n");
            break;
        }
改成这样子试一下:
 
    int write_length=fwrite(buf,sizeof(char),length,fp);
flush(fp);//fwrite之后马上刷新缓存看看。
        if(write_length<length)
        {
            printf("Write Failed!\n");
            break;
        }
引用 78 楼 lovesmiles 的回复:
fflush(fp);
两个都是大神!!!终于解决了文件传输的问题。现在终于能够收到完整的文件了!!但是客户端一直会卡在"Finished"那里。不知道为什么。我准备写一个判断文件结尾的语句来break,不知道行不行?
勤奋的小游侠 2014-08-02
  • 打赏
  • 举报
回复
引用 80 楼 Zidane_2014 的回复:
[quote=引用 76 楼 lovesmiles 的回复:] 看你的截图,数据全部收到了buff了吧。你是不是经常用ctrl^D来结束程序?
     int write_length=fwrite(buf,sizeof(char),length,fp);
        if(write_length<length)
        {
            printf("Write Failed!\n");
            break;
        }
改成这样子试一下:
 
    int write_length=fwrite(buf,sizeof(char),length,fp);
flush(fp);//fwrite之后马上刷新缓存看看。
        if(write_length<length)
        {
            printf("Write Failed!\n");
            break;
        }
引用 78 楼 lovesmiles 的回复:
fflush(fp);
两个都是大神!!!终于解决了文件传输的问题。现在终于能够收到完整的文件了!!但是客户端一直会卡在"Finished"那里。不知道为什么。我准备写一个判断文件结尾的语句来break,不知道行不行?[/quote] 再说一次,请在客户端也使用select 模型。
Zidane_2014 2014-08-02
  • 打赏
  • 举报
回复
引用 82 楼 lovesmiles 的回复:
[quote=引用 80 楼 Zidane_2014 的回复:] [quote=引用 76 楼 lovesmiles 的回复:] 看你的截图,数据全部收到了buff了吧。你是不是经常用ctrl^D来结束程序?
     int write_length=fwrite(buf,sizeof(char),length,fp);
        if(write_length<length)
        {
            printf("Write Failed!\n");
            break;
        }
改成这样子试一下:
 
    int write_length=fwrite(buf,sizeof(char),length,fp);
flush(fp);//fwrite之后马上刷新缓存看看。
        if(write_length<length)
        {
            printf("Write Failed!\n");
            break;
        }
引用 78 楼 lovesmiles 的回复:
fflush(fp);
两个都是大神!!!终于解决了文件传输的问题。现在终于能够收到完整的文件了!!但是客户端一直会卡在"Finished"那里。不知道为什么。我准备写一个判断文件结尾的语句来break,不知道行不行?[/quote] 再说一次,请在客户端也使用select 模型。[/quote]我加了个if判断语句,现在可以执行完整程序了。谢谢指导!!
xiaohuh421 2014-08-01
  • 打赏
  • 举报
回复
二进制方式读取, 二进制方式传送, 二进制方式写入. 你的问题应该是数据本身就有问题了. 你先试试发送一个自己在内存中构造的buffer, 看能否正常发送和接收. 如果能, 那就是你读取的数据有问题了.
Zidane_2014 2014-08-01
  • 打赏
  • 举报
回复
引用 46 楼 zilaishuichina 的回复:
那就是recv返回0了嘛, socket被关掉了, 然后length=0, while条件不成立,循环直接结束了,然后你后面打印的还是success 你可以这样写


    int length=0;
    while(true)
    {
        length=recv(client_socket,buf,BUFFERSIZE,0)

        if(length==0)
        {
            printf("socket closed!\n");
            break;
        }

        if(length<0)
        {
            printf("Receive Data Failed!\n");
            break;
        }
         
        int write_length=fwrite(buf,sizeof(char),length,fp);
        if(write_length<length)
        {
            printf("Write Failed!\n");
            break;
        }
        bzero(buf,BUFFERSIZE);
    }
改成这样,连数据都收不到了。运行程序后,程序就一直卡在"Finished!"这里
勤奋的小游侠 2014-08-01
  • 打赏
  • 举报
回复
我说,你改成select IO试下嘛。为什么一定要用一个阻塞的read呢?还把它放到一个while里面。
zilaishuichina 2014-08-01
  • 打赏
  • 举报
回复
那就是recv返回0了嘛, socket被关掉了, 然后length=0, while条件不成立,循环直接结束了,然后你后面打印的还是success 你可以这样写


    int length=0;
    while(true)
    {
        length=recv(client_socket,buf,BUFFERSIZE,0)

        if(length==0)
        {
            printf("socket closed!\n");
            break;
        }

        if(length<0)
        {
            printf("Receive Data Failed!\n");
            break;
        }
         
        int write_length=fwrite(buf,sizeof(char),length,fp);
        if(write_length<length)
        {
            printf("Write Failed!\n");
            break;
        }
        bzero(buf,BUFFERSIZE);
    }
Zidane_2014 2014-08-01
  • 打赏
  • 举报
回复
引用 44 楼 zilaishuichina 的回复:
那就是不止1字节, 这显然不止1字节

如果lz确认抓包了, 服务端发来的数据是有最后的
</dev>
</devices>
</msg>
这些内容的

那么可能就是recv的问题了,
比如设置的是阻塞还是非阻塞,
比如是不是你这边还在循环recv中,对端已经close了而不是shutdown

lz实际出问题的代码,应该不是lz现在贴出来的代码吧
代码绝对是这个代码。
我用了wireshark抓包后follow TCP stream,显示的结尾:

说明服务端是传过来的。
我现在正在gdb那个while循环,看每一次的结果。
cyd54454 2014-08-01
  • 打赏
  • 举报
回复
引用 22 楼 Zidane_2014 的回复:
如何能避免死循环呢?
让服务器端关闭套接字就好了,这样recv返回就是0了。send.xml就算是发给服务器,你接收的时候,是按你给定的缓冲区大小来接收的,如果缓冲大小小于实际大小,就只返回缓冲区大小的内容。所以我想你看下send.xml里的字节数是不是比BUFFERSIZE大了
zilaishuichina 2014-08-01
  • 打赏
  • 举报
回复
那就是不止1字节, 这显然不止1字节 如果lz确认抓包了, 服务端发来的数据是有最后的 </dev> </devices> </msg> 这些内容的 那么可能就是recv的问题了, 比如设置的是阻塞还是非阻塞, 比如是不是你这边还在循环recv中,对端已经close了而不是shutdown lz实际出问题的代码,应该不是lz现在贴出来的代码吧
Zidane_2014 2014-08-01
  • 打赏
  • 举报
回复
引用 40 楼 zilaishuichina 的回复:
[quote=引用 38 楼 Zidane_2014 的回复:]
[quote=引用 36 楼 zilaishuichina 的回复:]
[quote=引用 35 楼 Zidane_2014 的回复:]
[quote=引用 30 楼 zilaishuichina 的回复:]
[quote=引用 29 楼 Zidane_2014 的回复:]
[quote=引用 25 楼 mymtom 的回复:]
查下少了哪个字节啊,这样可以帮助判断错误的原因。


引用 27 楼 zilaishuichina 的回复:
少一个字节 少的是什么? 是最后一个‘〉’么? 是不是任意一个文件都是少最后这个字符?


引用 28 楼 WizardOz 的回复:
跟本就没有EOF这个字符,EOF只是函数的返回值而已,如果少了一个字符,可能是少了'\r'之类的,建议LZ把文件内容用16进制的方式打印出来,这样看的最清楚,到底少了什么。
左边是正常情况,12289bytes。右边是不正常的情况,12288bytes。
正常结尾:
不正常结尾:[/quote]

</dev>
</devices>
</msg>
这个显然不是少1字节吧[/quote]?? size显示是不准确的吗?[/quote]

不一定是size不准确, 而是我们眼睛看到的字符,不一定就是文件里面实际有的字符,你后面没显示出来的内容,有可能是空格呀,回车符啊,换行符啊,ASCII表里面并不是每一个字符都能在文本当中显示出来的呀。
[/quote]恩。也就是说,size显示的是能看到的大小?[/quote]

size显示的是真实大小(包括那些看不见的字符),你建个空文本,按10次enter键,你看到的文本内容可能什么也没有,但是你看文件的size可能是20字节

所以你的例子里面,在xml里面看到的内容缺的不止一个字节,但是size显示少一个字节,也就是说明你看到内容后面还跟着一些你看不到的内容,所以需要用16进制显示,这样才能把看不到的内容也显示出来,这样才能知道这些看不到的内容具体是什么字符,然后最后缺了一个什么字符.

[/quote]用Bcompare比较了下:

history行的16进制:
dev行的16进制:
devices行的16进制:
msg行的16进制:
zilaishuichina 2014-08-01
  • 打赏
  • 举报
回复
引用 39 楼 Zidane_2014 的回复:
引用 37 楼 cyd54454 的回复:
你在服务器端,也保存一个文件看看,是同样少字节还是完整的。要是完整的就把服务器端的接收代码改改弄到客户端。要还出错,那服务器端发送就有问题了
服务端我接触不到。
你可以模拟一个服务端, 把你代码里面接受,和发送的代码分成两个程序来测试
cyd54454 2014-08-01
  • 打赏
  • 举报
回复
引用 39 楼 Zidane_2014 的回复:
服务端我接触不到。
额,你调试的时候,查看客户端recv函数写入buf里的内容是完整的么,还是说那里就已经缺失了。要是这样的话,服务器返给你的数据就少了。
zilaishuichina 2014-08-01
  • 打赏
  • 举报
回复
引用 38 楼 Zidane_2014 的回复:
[quote=引用 36 楼 zilaishuichina 的回复:] [quote=引用 35 楼 Zidane_2014 的回复:] [quote=引用 30 楼 zilaishuichina 的回复:] [quote=引用 29 楼 Zidane_2014 的回复:] [quote=引用 25 楼 mymtom 的回复:] 查下少了哪个字节啊,这样可以帮助判断错误的原因。
引用 27 楼 zilaishuichina 的回复:
少一个字节 少的是什么? 是最后一个‘〉’么? 是不是任意一个文件都是少最后这个字符?
引用 28 楼 WizardOz 的回复:
跟本就没有EOF这个字符,EOF只是函数的返回值而已,如果少了一个字符,可能是少了'\r'之类的,建议LZ把文件内容用16进制的方式打印出来,这样看的最清楚,到底少了什么。
左边是正常情况,12289bytes。右边是不正常的情况,12288bytes。 正常结尾: 不正常结尾:[/quote] </dev> </devices> </msg> 这个显然不是少1字节吧[/quote]?? size显示是不准确的吗?[/quote] 不一定是size不准确, 而是我们眼睛看到的字符,不一定就是文件里面实际有的字符,你后面没显示出来的内容,有可能是空格呀,回车符啊,换行符啊,ASCII表里面并不是每一个字符都能在文本当中显示出来的呀。 [/quote]恩。也就是说,size显示的是能看到的大小?[/quote] size显示的是真实大小(包括那些看不见的字符),你建个空文本,按10次enter键,你看到的文本内容可能什么也没有,但是你看文件的size可能是20字节 所以你的例子里面,在xml里面看到的内容缺的不止一个字节,但是size显示少一个字节,也就是说明你看到内容后面还跟着一些你看不到的内容,所以需要用16进制显示,这样才能把看不到的内容也显示出来,这样才能知道这些看不到的内容具体是什么字符,然后最后缺了一个什么字符.
Zidane_2014 2014-08-01
  • 打赏
  • 举报
回复
引用 37 楼 cyd54454 的回复:
你在服务器端,也保存一个文件看看,是同样少字节还是完整的。要是完整的就把服务器端的接收代码改改弄到客户端。要还出错,那服务器端发送就有问题了
服务端我接触不到。
Zidane_2014 2014-08-01
  • 打赏
  • 举报
回复
引用 36 楼 zilaishuichina 的回复:
[quote=引用 35 楼 Zidane_2014 的回复:] [quote=引用 30 楼 zilaishuichina 的回复:] [quote=引用 29 楼 Zidane_2014 的回复:] [quote=引用 25 楼 mymtom 的回复:] 查下少了哪个字节啊,这样可以帮助判断错误的原因。
引用 27 楼 zilaishuichina 的回复:
少一个字节 少的是什么? 是最后一个‘〉’么? 是不是任意一个文件都是少最后这个字符?
引用 28 楼 WizardOz 的回复:
跟本就没有EOF这个字符,EOF只是函数的返回值而已,如果少了一个字符,可能是少了'\r'之类的,建议LZ把文件内容用16进制的方式打印出来,这样看的最清楚,到底少了什么。
左边是正常情况,12289bytes。右边是不正常的情况,12288bytes。 正常结尾: 不正常结尾:[/quote] </dev> </devices> </msg> 这个显然不是少1字节吧[/quote]?? size显示是不准确的吗?[/quote] 不一定是size不准确, 而是我们眼睛看到的字符,不一定就是文件里面实际有的字符,你后面没显示出来的内容,有可能是空格呀,回车符啊,换行符啊,ASCII表里面并不是每一个字符都能在文本当中显示出来的呀。 [/quote]恩。也就是说,size显示的是能看到的大小?
cyd54454 2014-08-01
  • 打赏
  • 举报
回复
你在服务器端,也保存一个文件看看,是同样少字节还是完整的。要是完整的就把服务器端的接收代码改改弄到客户端。要还出错,那服务器端发送就有问题了
zilaishuichina 2014-08-01
  • 打赏
  • 举报
回复
引用 35 楼 Zidane_2014 的回复:
[quote=引用 30 楼 zilaishuichina 的回复:] [quote=引用 29 楼 Zidane_2014 的回复:] [quote=引用 25 楼 mymtom 的回复:] 查下少了哪个字节啊,这样可以帮助判断错误的原因。
引用 27 楼 zilaishuichina 的回复:
少一个字节 少的是什么? 是最后一个‘〉’么? 是不是任意一个文件都是少最后这个字符?
引用 28 楼 WizardOz 的回复:
跟本就没有EOF这个字符,EOF只是函数的返回值而已,如果少了一个字符,可能是少了'\r'之类的,建议LZ把文件内容用16进制的方式打印出来,这样看的最清楚,到底少了什么。
左边是正常情况,12289bytes。右边是不正常的情况,12288bytes。 正常结尾: 不正常结尾:[/quote] </dev> </devices> </msg> 这个显然不是少1字节吧[/quote]?? size显示是不准确的吗?[/quote] 不一定是size不准确, 而是我们眼睛看到的字符,不一定就是文件里面实际有的字符,你后面没显示出来的内容,有可能是空格呀,回车符啊,换行符啊,ASCII表里面并不是每一个字符都能在文本当中显示出来的呀。
Zidane_2014 2014-08-01
  • 打赏
  • 举报
回复
引用 30 楼 zilaishuichina 的回复:
[quote=引用 29 楼 Zidane_2014 的回复:] [quote=引用 25 楼 mymtom 的回复:] 查下少了哪个字节啊,这样可以帮助判断错误的原因。
引用 27 楼 zilaishuichina 的回复:
少一个字节 少的是什么? 是最后一个‘〉’么? 是不是任意一个文件都是少最后这个字符?
引用 28 楼 WizardOz 的回复:
跟本就没有EOF这个字符,EOF只是函数的返回值而已,如果少了一个字符,可能是少了'\r'之类的,建议LZ把文件内容用16进制的方式打印出来,这样看的最清楚,到底少了什么。
左边是正常情况,12289bytes。右边是不正常的情况,12288bytes。 正常结尾: 不正常结尾:[/quote] </dev> </devices> </msg> 这个显然不是少1字节吧[/quote]?? size显示是不准确的吗?
加载更多回复(63)

69,373

社区成员

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

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