日期:2014-05-16  浏览次数:20934 次

LINUX下socket传输多张图像数据,有误,丢帧严重
传输一张图像已成功,传输4张图像出错,每张图像32K,服务器端每次send 1k,发送32次。
for(m=0;m<num;m+=1024) //传输jpg图像数据
  {
  n=send(clientfd,buff+m,1024,0);
  if(n==-1) perror("send error");
  printf("n:%d\n",n);  
  }
客户端每次recv 1K,接收32次。
for(m=0;m<MAXDATA;m+=1024)
  {
  n=recv(sockfd,buff+m,1024,0);
if(n==-1) perror("recv fail\n");
  printf("n:%d\n",n); 
}

服务器端可以发送出去数据,只能发送3帧,发送到第4帧,出错:send error: Connection reset by peer

客户端接收到的数据不全,有丢失。而且只能接收一帧,图像很模糊不清。

------解决方案--------------------
recv做下while处理吧,不能保证1024都收全呀
------解决方案--------------------
tcp是没有数据边界的,所以你的 m 不应该+= 1024, 而应该 m += n

按照你的程序写法,客户端很可能先于服务器关闭fd, 因为客户端可能错误的认为数据接收完了
------解决方案--------------------
这种连续收发的程序,最好带个帧头。帧尾,。客户端接收的时候,收取的数据先放一个缓冲区,按照帧头,帧尾来解析,解析到正确的一帧就重缓冲区删掉,,以此循环。。。这样可以避免粘包的问题。和缓解服务器端压力。
------解决方案--------------------
探讨

引用:
recv做下while处理吧,不能保证1024都收全呀

修改了下:
while(recvbytes<MAXDATA)
{
n=recv(sockfd,buff+recvbytes,MAXDATA,0);
if(n==-1) perror……

------解决方案--------------------
LS有好几位提出了组包,判断合法的包就解析出来。这个主意不错。有个简单的协议比较合适。
------解决方案--------------------
C/C++ code

m = num;
ptr = buff;
while (m > 0)
{
    n = send(clientfd, ptr, m, 0);
    if (n == -1) ...
    ptr += n;
    m -= n;
    printf("n:%d\n", n);
}

------解决方案--------------------
楼主,你的代码不安全.
接收部分的代码,是不能保证一次能接收到1024个或者固定个字节的.能接受多少是随机的.
因此,按照其他人的建议,修改为循环接收可以解决问题.
另外你说的会不会溢出的问题,这样回答:首先,一共接收多少个字节你是知道的,收够了,就退出循环.这样就不会溢出了.

至于说到的简单协议的问题,可以这样.发送32K图像之前,发送个头.
比如
4字节:type (你可以自己定义一个值,例如PIC_TYPE)
4字节:length (对应你的代码就是32K)
length字节:data (从这里发送图像数据)

另外,你还可以把4个图像组合成一个大包,也发一个包头
比如:
4字节:type (你可以自己定义一个值,例如PICGROUP_TYPE)
4字节:length (对应你的是4张图片+4个图片头=(4+4+32K)*4)
length字节:data (从这里发送4张图像的数据,保护头)

这样,在你的接收代码里面,读取这些包头,来决定如何处理.

可以参考一下用tcp/ip进行网际互联,随便参考一个协议.了解一下协议是要做些什么.