首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

TCP发送数据丢掉的原因

2013-09-04 
TCP发送数据丢失的原因从服务器上发送数据,在客户机上接收,以前很正常,现在服务器端网络升级了网络带宽,发

TCP发送数据丢失的原因
从服务器上发送数据,在客户机上接收,以前很正常,现在服务器端网络升级了网络带宽,发送数据稍大时就丢失数据,客户机无法收到,采用发送-应答方式,也没有办法。

而且丢失数据很有规律。

每次发送1000+8个子节,到了第10次接收,就只能收几百个字节了


请高手指点一下原因,多谢!
[解决办法]
有没有把32位的变量改成64位的,或是反过来?查查吧。调试下吧,很容易查出问题,应该和网络没什么关系。
[解决办法]

引用:
补充:在局域网测试没有问题,服务器在外网就有问题。
以前服务器发送数据很简单:如下
                 bytesSent = handle.Send(sendbuf );

客户端也可收到,后来服务器所在网络升级了,数据一大就丢失,好像数据大于1024X10 就不行了。
 后来服务器改为分段发送,每次发送1024+8个字节,然后等待客户端回应,收到回应后发下一个1024+8的数据,可是到了第10次,还是收不到数据,不知为何?
                       
查代码吧,必须的
[解决办法]
看上去很象Socket.ReceiveBufferSize缺省大小是8192,接收9次左右,每次1000字节,差不多就是这个大小。

如果是这个原因,说明你的接收处理程序处理太慢了,缓冲区容不下新到的数据了。

你应该自己规定个协议,如果对方发送速度太快了,就让对方停下,等到你这边处理完了再发个标志给对方继续发送。

[解决办法]
引用:
现在服务器发送代码:   public int Sendbytes(byte [] bytes)//待发数据在数组中
        {
           
            int bytesSent=0;
           
            int page, n,k,t;
            n = bytes.Length;
            int sendtimes = 1;//连续发送次数sendtimes=1,若设为10表示发10个包再确认一次
            int sendbytes=1000;//每次发送数据大小
            page = 0;  //发送页面
            byte[] sendbuf = new byte[sendbytes + 8];//发送缓冲区


            int off0,off, l;// off:偏移量  l:数据长度,
            //发送缓冲区格式:   数据长度(4字节),数组偏移量(4字节),发送数据(1000)
            byte[] bsize;
            byte[] boff;
            string sre;
            bool sendover = false;//发送结束标志
            while (true)
            {
                page++; //发送 第一个页面 page=1

                t = 0;//设置重复发送次数,若重复发送3次还是没有收到客户端确认,就退出发送过程
                while (true)
                {
                    t++;
                    k = 0;
                  
                    off0 = (page - 1) * sendtimes * sendbytes;//每次发送一个页面的起始偏移量
                    while (k < sendtimes)
                    {
                        off = off0 + k * sendbytes; //数据所在数组缓冲区偏移位置(索引)
                        if (off < n - sendbytes)//本次发送后,还有待发数据
                            l = sendbytes;//l 表示发送数据大小,如1000,
                        else if (off == n - sendbytes)//本次刚好发送完成


                        {
                            l = sendbytes;
                            sendover = true;  //发送结束标志为真
                        }
                        else if (off >= n)
                        {
                            //发送完毕
                            l = 0;
                            sendover = true;
                            break;
                        }
                        else
                        {
                            l = n - off;//发送最后少于1000的数据
                            sendover = true;

                        }
                    //将数据大小,数组偏移量,实际数据写入发送缓冲区
                        bsize = BitConverter.GetBytes(l);


                        boff = BitConverter.GetBytes(off);
                        bsize.CopyTo(sendbuf, 0);
                        boff.CopyTo(sendbuf, 4);
                        Array.Copy(bytes, off, sendbuf, 8, l);
                        try
                        {
                            bytesSent = handle.Send(sendbuf );
                        }
                        catch
                        {

                        }
                        k++;
                    }//(k < sendtimes)
                   
                 
                        //等待接受确认,接收4个子节的确认数据,等待时间为3秒
                        sre = Receivedata(4, 3);
                       
                        if (sre == "1234" 


[解决办法]
t>5)  //收到了确认,或重发了3次,可能客户端退出了
                            break;
                    

                }//while (true) 重新发送一个页面的所有记录

                if (sendover)
                    break;


            }//while (true)

            return 1;

        }

为什么要确认呢?tcp已经是可靠的了,不是多此一举吗?正常的发送接收不是判断长度的吗?你整个次数,也太理想了吧?要想确认除非你发一个接收一个,再回发一个,然后再发一个,。。。。。
[解决办法]
问题可能是在客户端的接收部分,代码呢?
[解决办法]

bytesRec = sender.Receive(bytes );//接收数据,1000+8的缓冲区
if (bytesRec == sendbytes + 8)

这里有问题。

注意TCP不是包协议,不保证发一个包,就每次接收也是一个包。
可能这次只收到半个包,也可能收到一个半, 下次再收到半个。

你要自己合并接收数据,再分包。

[解决办法]
TCP发送数据不处理粘包肯定是不行的,而且要提高效率,接收和解析最好分离,推荐解析数据用线程池
[解决办法]
代码写得有问题,80%

热点排行