LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 997|回复: 7

[请教]socket 文件传输问题

[复制链接]
发表于 2006-12-30 16:31:54 | 显示全部楼层 |阅读模式
使用流套结字,同时写了客户端和服务端,
现在的问题是,我把客户端和服务端同时在自己机器上测试, 传输没发现什么问题.

但是在两台不同的机器上运行客户端和服务端,
如果是传输pdf等文本文件,接收的文件没什么问题,

如果服务端接收到的文件是图片,第一次传过去不能浏览,
重传一遍就可以浏览了,但是图片内容与实际不相符,
图片显示时中间有条条框框.

在程序里面,在客户端文件每次发送8192个字节,
服务端每次从套结字中按照这个字节数进行读取再保存
不知道是不是在分开打包传输后接收时出了问题?
但是为什么在本机上却没有问题呢?

client端分隔文件发送部分代码:
[php]
#define BUF_SIZE    8192

...........
        read_times = file_size /(BUF_SIZE) ;
        read_left = file_size % (BUF_SIZE) ;

        if(file_size>=BUF_SIZE)
        for(i=1; i<=read_times; i++)
        {
                bzero(buffer,BUF_SIZE);
                read(fd,buffer,BUF_SIZE);
                write(s,buffer,BUF_SIZE);
        }
        bzero(buffer,BUF_SIZE);
        read(fd,buffer,read_left);//read left data
        write(s,buffer,read_left);//save left data
[/php]

server端接收部分代码:
[php]
                if(file_size>=BUF_SIZE)
        for(i=1; i<=read_times; i++)
        {
                bzero(buffer,BUF_SIZE);
                read(ns,buffer,BUF_SIZE);
                write(fd,buffer,BUF_SIZE);//save to the opened file
        }
        bzero(buffer,BUF_SIZE);
        read(ns,buffer,read_left);//read left data
        write(fd,buffer,read_left);//save left data
[/php]

各位帮看看 , 问题出在什么地方呢?
发表于 2006-12-30 17:07:30 | 显示全部楼层
不明白为什么上面 for 循环语句里面执行 bzero read write 后外面再执行一次
read_left指什么?
还有,for循环好像用的不大好,因为要传输的字节不是刚好整数个 BUF_SIZE
要有判断数据结束的语句,具体怎么,还得请教高手,如什么EOF或\0之类

我也是菜鸟,说错了请指教!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-12-30 17:24:50 | 显示全部楼层
Post by hoho_zhao
不明白为什么上面 for 循环语句里面执行 bzero read write 后外面再执行一次
read_left指什么?
还有,for循环好像用的不大好,因为要传输的字节不是刚好整数个 BUF_SIZE
要有判断数据结束的语句,具体怎么,还得请教高手,如什么EOF或\0之类

我也是菜鸟,说错了请指教!
不好意思,可读性不好, 因为前面设置了一个BUF_SIZE,如果文件比BUF_SIZE大,那么根据文件大小来计算有多少个BUF_SIZE(程序里表示有read_times个BUF_SIZE,可能还有一部分没有BUF_SIZE大的read_left数据,即文件大小= read_times*BUF_SIZE+read_left. 如果文件没有BUF_SIZE大就不用循环了,直接一次发送过去了.

我这里没有用EOF去判断是否结束,因为我计算出了文件的大小,按照字节来读取这个文件的,直到读取到最后一个字节.应该不会不相符合吧.
回复 支持 反对

使用道具 举报

发表于 2006-12-30 18:16:58 | 显示全部楼层
tcp是流式协议,不能保证你服务端每次收到的包长度就是原始的8192字节,要是某一个你read只读到4096字节,那按照你的for循环,可能就丢了4096字节了,能对么
回复 支持 反对

使用道具 举报

发表于 2006-12-30 21:58:32 | 显示全部楼层
晕!不好意思,我看错了 read_left 中的 left 是 leave的过去分词,
我以为跟 right 相对的 left !没二想,发问了。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-12-31 09:32:21 | 显示全部楼层
Post by x11
tcp是流式协议,不能保证你服务端每次收到的包长度就是原始的8192字节,要是某一个你read只读到4096字节,那按照你的for循环,可能就丢了4096字节了,能对么


流套结字不是没收到就重发么?

怎么才能保证不丢包??
回复 支持 反对

使用道具 举报

发表于 2006-12-31 10:51:48 | 显示全部楼层
跟重发没啥关系,而是你要求接受8192字节,实际收到的不一定就是8192字节,而你当作8192字节计算已接收的长度,数据就被你丢了,不是网络丢了,是被你丢了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-4 17:01:43 | 显示全部楼层
Post by x11
跟重发没啥关系,而是你要求接受8192字节,实际收到的不一定就是8192字节,而你当作8192字节计算已接收的长度,数据就被你丢了,不是网络丢了,是被你丢了

你说的没错,我重新修改了代码.如果没读取到BUF_SIZE个字节,则重新计算剩余字节数,把那个循环去掉,重新写了个小循环就欧了.

只是有个疑问问X11,是不是某个读取的时刻,socket缓冲里面有可能数据不够我要读取的字节数,按照我的循环,自以为读取到了,而实际每次会被自己丢掉一部分.那么怎么才能知道socket里缓冲里到底有多少个字节呢?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表