C# Socket通信丢包的问题

Nickiven007 2015-02-26 04:32:21
本人用C# Socket套接字技术 写了一个上位机程序 接收下位机上传的数据。下位机每8.4ms发送一帧数据 电脑接收以后 先存在一个缓存数组Buffer1内 当接收满1000帧后 将Buffer1丢到线程池 用FileStream进行写操作 存入硬盘。此时套接字继续接收数据 为了避免并发冲突 此时缓存数组更换为Buffer2。Buffer2接收满后 在丢到线程池 Buffer1 重新顶上进行缓存,如此交替进行。此程序在我的电脑上 运行没有问题。我的电脑为win7的系统 I3的处理器。但是当我将程序在另一台电脑上运行时 发现各种丢包。我将程序中不必要的线程池(包括数据解析)操作全都注释起来,仅保留Socket接收,丢包数下降 但是平均每天仍然有一帧(8.4ms)的数据丢失。另一台电脑为XP系统 Core2 Duo的处理器。比较老的破机子了。
是因为电脑配置的问题导致丢包么 如何解决这个问题啊?本人新手 虚心受教了 请大家帮帮我。
另:Socket套接字在一个Background线程中 由一个ChoiceBox控制启停
...全文
1045 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
生财 2015-03-06
  • 打赏
  • 举报
回复

楼主可以这样写
byte[] recbuff=new byte[1024*1024]
List<byte[]> list=new List<byte[]>();
while(clientSocket.Connectioned)
{
 int len= clientSocket.Receive(recbuff);
   //这里可以用array copy 方法复制
   //为了简单用Linq了
  var data=recbuff.Take(len);
lock(list)
{
//添加到集合中
list.Add(data);
}
}

///////////////////////外面取list值
lock(list)
{
    data = list[0];
    list.Remove(0)
}

//楼主用以上方法试试
kingdom_0 2015-03-02
  • 打赏
  • 举报
回复
抛开粘包不说,设计思路也有问题。 典型的生产者消费者问题,一个buffer作为缓冲区足够了
足球中国 2015-03-01
  • 打赏
  • 举报
回复
引用 9 楼 xian_wwq 的回复:
[quote=引用 6 楼 Nickiven007 的回复:] [quote=引用 1 楼 lincolnandlinda 的回复:] 把Socket接收帧的那块代码贴出来看看
请指教 [/quote] 感觉接收逻辑有些问题 你接收到的长度不一定是1024,怎么能循环按照1024拷贝呢? 不管网络状况是否良好,“粘包”处理是少不了的 [/quote] 就是, 这个不是丢包,是根本没有对粘包做处理。最起码的
PaulyJiang 2015-02-28
  • 打赏
  • 举报
回复
丢包应该是网络问题,代码需要处理
Sunny5816 2015-02-28
  • 打赏
  • 举报
回复
朋友,您可以尝试一下英国的开源的NetworkComms2.31 通信框架 (c#语言)
Sunny5816 2015-02-28
  • 打赏
  • 举报
回复
来学习
xian_wwq 2015-02-27
  • 打赏
  • 举报
回复
1.估算下最大的数据量,如果百兆网卡带宽占用不到10M以上, 可以肯定的说不是网络导致的丢包, 2.查一下数据接收逻辑,是不是在接收时,进行了其他逻辑校验之类的工作。 把耗时的逻辑处理统统放到线程池中去, 接收逻辑要尽可能的简化,收到数据,放入buffer,本次操作就返回。
  • 打赏
  • 举报
回复
那个例子的帖子地址是这个:http://bbs.csdn.net/topics/390987992 不要总是把时间全都花在底层代码上。最好达到那种程度,我们谈得主要都是是围绕“一个服务器控制几百台不同任务的客户端、十几台服务器协同组成集群”之时的信令设计和业务流程设计话题,而不是这些底层的代码。
  • 打赏
  • 举报
回复
你可以参考我贴出的一个“Base”的例子,参考其中的 container、len 和 buffer 的处理。 通讯部分应该做成一两个“基础程序”,以后各种应用只要重复使用它就好了(只要初始化对象参数、捕获其事件、调用其SendMessage方法就好了)。不要在各种应用中都去重写底层代码。
本拉灯 2015-02-27
  • 打赏
  • 举报
回复
..这么写不丢才怪。。
xian_wwq 2015-02-27
  • 打赏
  • 举报
回复
引用 6 楼 Nickiven007 的回复:
[quote=引用 1 楼 lincolnandlinda 的回复:] 把Socket接收帧的那块代码贴出来看看
请指教 [/quote] 感觉接收逻辑有些问题 你接收到的长度不一定是1024,怎么能循环按照1024拷贝呢? 不管网络状况是否良好,“粘包”处理是少不了的
Nickiven007 2015-02-27
  • 打赏
  • 举报
回复
引用 4 楼 xian_wwq 的回复:
1.估算下最大的数据量,如果百兆网卡带宽占用不到10M以上, 可以肯定的说不是网络导致的丢包, 2.查一下数据接收逻辑,是不是在接收时,进行了其他逻辑校验之类的工作。 把耗时的逻辑处理统统放到线程池中去, 接收逻辑要尽可能的简化,收到数据,放入buffer,本次操作就返回。
数据量8.4MS 1K算大么 接收就放入buffer 没有任何逻辑处理 上面贴了代码 请您看一下
Nickiven007 2015-02-27
  • 打赏
  • 举报
回复
引用 2 楼 daonidedie 的回复:
楼主,的程序数据量多大? TCP应该不会丢包.
数据量不大啊 8.4MS 1K
Nickiven007 2015-02-27
  • 打赏
  • 举报
回复
引用 1 楼 lincolnandlinda 的回复:
把Socket接收帧的那块代码贴出来看看

请指教
s8848 2015-02-27
  • 打赏
  • 举报
回复
网卡存在的问题,网卡有时候自己会自做主张的把包了.尤其是当cpu卡的时候.
长空X 2015-02-26
  • 打赏
  • 举报
回复
会不会是电脑配置或网络环境的问题呢?还有就是收包时的逻辑、。这几个地方有可能就是影响的
生财 2015-02-26
  • 打赏
  • 举报
回复
楼主,的程序数据量多大? TCP应该不会丢包.
lincolnandlinda 2015-02-26
  • 打赏
  • 举报
回复
把Socket接收帧的那块代码贴出来看看
SanNiuSignal是一个基于异步socket的完全免费DLL;它里面封装了Client,Server以及UDP;有了这个DLL;用户不用去关心心跳;粘包 ;组包;发送文件等繁琐的事情;大家只要简单的几步就能实现强大的通信系统;能帮助到大家是本人觉得最幸福的事情,也希望大家 在用的过程中找出DLL中不足的地方;好改正;此DLL的苹果版和java版正在努力开发中......交流QQ:365368248;此演示源码下载地址:http://pan.baidu.com/s/1eQw1npw 里面包括了SanNiuSignal.DLL 下面为大家介绍一下 如何使用SanNiuSignal. 1 ) :TCPServer服务器,通过静态方法TxStart.startServer注册成功服务器ITxServer;然后通过ITxServer设置好各种属性;最后启动 ITxServer.StartEngine();就可以了;具体可以到demo里去看;相对来说比较简单,下面来说一下需要注意的地方 一:ITxServer.BufferSize,就是接收数据缓冲区大小;默认为1kb,不要小于50字节,而且要和客户端设置成一样;否则会出现不可预知 的错误;这个缓冲区的大小,不会影响你每次发送数据的大小;大小只能提高你的发送速度 二:ITxServer.sendMessage 发送前先判断此IPEndPoint客户端是否在线;因为如果不在线等情况发生;此方法没有任何消息产生;如 果发送成功并且对方已经收到;会触发发送成功的事件; 三:用户可以通过ITxServer.FileLog记录服务器的运行信息; 2 ) :TCPClient客户端,通过静态方法TxStart.startClient(服务器地址或网址, 服务器端口号)注册成功客户端ITxClient;然后通过 ITxClient设置好各种属性;最后启动ITxClient.StartEngine();跟服务器启动差不多;具体可以到demo里去看;客户端要注意的一些地 方 一:如果非服务器强制关闭客户端的情况下,掉线的话,客户端默认是要重连的;他的原理是这样的,每10秒重连一次;重连 ITxClient.ReconnectMax次如果失败;会自动关闭客户端引擎;在重连的过程中;你可以改变客户端连接服务器的IP地址和端口号;但 如果当断开的时候不想重连;可以设置ITxClient.ReconnectMax=0; 二:登录篇,在引擎启动之前,用户可以设置ITxClient.OutTime来设置超时时间;默认为10秒,也就是说10秒之内肯定会有一个登录结果 ;登录成功或登录失败。有了登录结果会触发登录结果事件; 3 ) :Udp引擎,通过静态方法TxStart.startUdp()注册成功UDP--IUdpTx;然后通过IUdpTx设置好各种属性;最后启动 IUdpTx.StartEngine();如果在启动之前要绑定端口号,请在这里设置IUdpTx.Port;否则是随机使用本地端口;无论是UDP还是服务器和 客户端;它们的很多方法和属性以及事件都是相同的,因为他们都继承了通信系统的基接口ITxBase;下面是UDP引擎要注意的地方 一:UDP的优势在于速度快但不太可靠;所以有些属性不能设置的太过,如IUdpTx.BufferSize;默认为1KB,如果在广域网上发送信息, 缓冲区大小不要超过默认值;否则数据会丢失,如果一次性数据大于1KB;也没事,系统会自动分包发送;不太会丢包。 4 ) :文件发送系统,通过静态方法FileStart.StartFileSend(IFileSendMust)生成一个文件发送系统IFileSend;其中IFileSendMust是 必须实现的一个接口;具体参照demo;然后通过IFileSend设置好各种属性;发送还是要通过前面的三个引擎系统发送的;如 ITxClient.SendFile 这时会返回一个文件标签,是一个整数;IFileSend可以通过操作这个标签来操作这个正在发送的文件;接收文件 系统也一样;也是通过文件标签来操作;文件续传也是一样,也要通过前面的三个通信引擎系统进行续传;因为文件系统不能决定用户 通过哪个通信系统进行续传的;例如IUdpTx.ContinueFile进行续传;大家也可以试一下 掉线之后重新连接也可以续传; 5 ) :文件接收系统,通过静态方法FileStart.StartFileReceive(IFileReceiveMust)生成一个文件接收系统IFileReceive;其中 IFileReceiveMust是接收方必须实现的一个接口;具体参照demo;然后通过IFileReceive设置好各种属性;下面来讲讲文件系统要注意 的几个要点 一:每个文件都有一个文件标签,发送系统和接收系统是通过控制这个标签来控制这个文件的;如果是同一个文件传输,标签也一样的; 二:要注意属性BufferSize缓冲区大小,他是代表一次传送的字节数;如果这个文件缓冲区越大,传输速度越快;具体要设置成多少,大 家自己去调试;TCP传输的话一般可以设置成比较大,但UDP的话这个不要超过1KB;所以传输大文件尽量不要用UDP这种不可靠的东东; 三:当网络等各种原因中断文件的时候;会触发文件中断事件;文件自动处于暂停发送或接收状态;等待续传;续传的发送方,如果对方 同意续传;对方将不会触发续传开始的方法;别的大家可以通过demo里去发现; 总结: 其实这个DLL相对来讲是比较简单的;大家只要掌握这五个接口;1:ITxServer TCP服务器接口 2:ITxClient TCP客户端接口 3:IUdpTx UDP接口 4:IFileSend 文件发送方接口 5:IFileReceive 文件接收方接口 前面三个接口是通过TxStart启动;后面二个文件接口 是通过FileStart启动 今天先讲到这里;希望这个DLL对大家有所帮助;不足之处希望通过QQ或博客园大家一起交流;谢谢 此演示源码下载地址:http://pan.baidu.com/s/1eQw1npw 里面包括了SanNiuSignal.DLL

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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