为什么通过socket会丢数据?

libad 2003-07-18 11:09:51
从一个socket server的端口9990接收数据 ,数据量很大,我们客户端接收的数据老收不全,有丢报告的现象,但read和select函数都没有出错。不知什么原因?
尝试过把select的超时时间设大和不设超时,read 设成阻塞和非阻塞方式,但都不行,可如果手工telnet到9990端口上收报告,报告却不丢,不知什么原因?
如果不用read改用recv,应该怎么用呀?
代码如下:



while(1){
memset(buf,0x00,sizeof(buf));
FD_SET (sock,&readset);
//FD_ZERO (&readset);
select_time.tv_sec = 5;
select_time.tv_usec = 0;


rc_select = select (sock+1,&readset,NULL,NULL,&select_time);
if(rc_select == -1){/*select error*/
if(errno == EINTR) continue;
else{
log.write(LOG_DEV&LOGFILE_MASK|LOG_TIME|ERROR,
"%sselect socket reading status failed.\n",
ErrLogStr);
return -1;
}
}
else if(rc_select==0){/*timeout*/
break;
}
else if(rc_select > 0){
if(FD_ISSET(sock,&readset)){/*ready for reading*/
if((rc_read=read(sock,(void *)buf,sizeof(buf)))>0){
printf("\nget data here...\n");
}
else if(rc_read《=){}/* ISSET */
}
} //end while 1
...全文
259 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
zumesun 2003-07-22
  • 打赏
  • 举报
回复
对,不要太长,1k就够了。
shanglin 2003-07-22
  • 打赏
  • 举报
回复
最好每次不要超过1K,否则局域网内都会丢数据。
blh 2003-07-21
  • 打赏
  • 举报
回复
read 并不是每次读取你指定的大小的数据,一般是<=你要求的数据长度
痞子酷 2003-07-21
  • 打赏
  • 举报
回复
tcp如果是非阻塞方式,如果处理不过来,超时,没有进缓冲区的数据的数据就会丢失。
如果是阻塞方式,不会丢失数据。在write时被阻塞,只有缓冲区数据被读取后才能发送。
fierygnu 2003-07-21
  • 打赏
  • 举报
回复
TCP有流控和可靠传输机制,不是TCP的问题,不是缓存区的问题。
另外楼上说的“空格”问题也不对,没这回事。TCP是可靠的流传送,跟空格没关系。

楼主的问题可能是read被信号中断又没有循环读取。只是可能,因为你的select是循环的。
kp_flysky 2003-07-21
  • 打赏
  • 举报
回复
我想你还是要通过协议上和程序上都保证
协议上可以这样,消息长度+消息内容
读到消息长度后,要保证读到消息长度这么长的内容,才能保证是这个消息是完整的
socket你可以想象成一条连绵不断的河,发送的数据是不会丢失的!
recv函数可以制定读取的长度,你可以比较一下要读的长度和返回的长度是否相等
例如
int i = recv(sokcfd,buf,length,0);
if(i<length)
{读到的内容不完整,需要继续读}
else
{读到完整的包}
zumesun 2003-07-21
  • 打赏
  • 举报
回复
空格的问题的确是有的,我曾今遇到过。
不知楼主解决了没有,到底是怎么一回事,可以拿出来分享一下。
zumesun 2003-07-20
  • 打赏
  • 举报
回复
楼上的同志,我想TCP协议应该会帮我们控制好数据丢失的问题,我以前写过串口程序,就需要自己写代码控制。

关于这个问题,我想有个逻辑上的问题。首先你这样的模型是服务器端的模型,而你是客户端接受数据,完全没有必要用select系统调用,除非你这个客户端也作服务器的事情。你这样写看看有没有问题:
while(1)
{
int result = read(socket,buf,sizeof(buf));
if(result < 0){ //出错了
printf("Error!\n");
break;
}
else if( result == 0) { //已经断开连接
printf("Disconnect\n");
break;
}
else{ //我已经得到了数据,数据的长度就是result个字节
//handle the date of buf
}
}

不过在上述模型中,要设置超时。

另外,还有一个可能,比较隐蔽。比如你发了一个字符串,长度为1024个字节,但是最后4个字节都是空格。对发送端来说,它确实发了1024个字节,但是到了接受端,就只有1020个字节了。这样字节数就少了,您看看是不是这个原因。如果是的话,就需要自己定一个协议了。最简单的办法就是腾出前面2个字节表示消息的长度。

您再试一试!
1010101010 2003-07-20
  • 打赏
  • 举报
回复
我想肯定是发送数据太快,很快站满了缓冲区,以至于将旧的数据替换掉了!将Write设为阻塞方式即可。加大缓冲区不能从根本上解决问题。
salaciouswolf 2003-07-19
  • 打赏
  • 举报
回复
把SOCKET的读写窗口和程序中的接收BUFFER改大一些试试看
铖邑 2003-07-19
  • 打赏
  • 举报
回复
数据量大恐怕要控制一下流量。

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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