[C#]关于事件驱动的SOCKET类的优化
2009-08-22 08:50
274 查看
在上一篇《[C#]事件驱动的SOCKET类》的文章中,地址:http://blog.csdn.net/much0726/archive/2009/06/25/4296789.aspx,我简单写了一个客户端的SOCKET连接类,并将接收的数据通知到SOCKET事件和数据包事件中,由于本人经验的不足,在数据判断上出现一些问题,原来写的文章中,我也会注明下本篇对其进行的进一步修改:
不能将socket.Poll(-1, SelectMode.SelectRead)方法作为判断SOCKET是否可以读的标准,此方法不能检测某些类型的连接问题,例如,网络电缆中断或远程主机意外关闭。您必须尝试发送或接收数据以检测这些类型的错误。在CSDN的论坛上也有人指出这个问题了,并且在微软的MSDN上也有权威的解释:http://technet.microsoft.com/zh-cn/system.net.sockets.socket.poll.aspx.
我原来的代码在服务器上运行一段时间后(大概1天左右),会出现接收不到SOCKET数据的情况,我就在判断前后加上了日志跟踪,果然是这个方法判断上出了问题。在C#写的接收数据方法上并不需要多余的判断,只要直接使用socket.Receive()即可,如果接收的字节数为0或者抛出SocketException异常,就可以判断网络连接是否断开了。下面是修改后的代码:
小结
线程通知到上层事件后,外部事件挂接后,可以直接进行委托BeginInvoke(),在委托的方法中就可以直接操作界面控件了。
不能将socket.Poll(-1, SelectMode.SelectRead)方法作为判断SOCKET是否可以读的标准,此方法不能检测某些类型的连接问题,例如,网络电缆中断或远程主机意外关闭。您必须尝试发送或接收数据以检测这些类型的错误。在CSDN的论坛上也有人指出这个问题了,并且在微软的MSDN上也有权威的解释:http://technet.microsoft.com/zh-cn/system.net.sockets.socket.poll.aspx.
我原来的代码在服务器上运行一段时间后(大概1天左右),会出现接收不到SOCKET数据的情况,我就在判断前后加上了日志跟踪,果然是这个方法判断上出了问题。在C#写的接收数据方法上并不需要多余的判断,只要直接使用socket.Receive()即可,如果接收的字节数为0或者抛出SocketException异常,就可以判断网络连接是否断开了。下面是修改后的代码:
//接收线程 public void Thread_Read() { while (true) { try { //使用数据缓冲 byte[] DataBuffer = new byte[DataBufferSize - DataBufferSizeLast]; int receivedBytesCount = socket.Receive(DataBuffer, DataBufferSize - DataBufferSizeLast, SocketFlags.None); if (receivedBytesCount == 0) { //socket连接已断开 Socket_e.ResCode = "00000"; SocketEvent(this, Socket_e); return; } int iTempDataBufferSizeLast = 0; byte[] TempBytes = new byte[receivedBytesCount + DataBufferSizeLast]; //receivedBytesCount + DataBufferSizeLast if (DataBufferLast != null) { Buffer.BlockCopy(DataBufferLast, 0, TempBytes, 0, DataBufferSizeLast); iTempDataBufferSizeLast = DataBufferSizeLast; DataBufferLast = null; //---- 使用完后 为空值 DataBufferSizeLast = 0; } Buffer.BlockCopy(DataBuffer, 0, TempBytes, iTempDataBufferSizeLast, receivedBytesCount); EncodingBytes(TempBytes, receivedBytesCount + iTempDataBufferSizeLast); } catch (SocketException e) { //10035 == WSAEWOULDBLOCK if (e.NativeErrorCode.Equals(10035)) { //仍然处于连接状态,但是发送可能被阻塞 } else { //连接错误,返回错误代码:e.NativeErrorCode Socket_e.ResCode = e.NativeErrorCode.ToString(); SocketEvent(this, Socket_e); return; } } catch (Exception e) { //其他错误 Socket_e.ResCode = e.ToString(); SocketEvent(this, Socket_e); return; } } }
小结
线程通知到上层事件后,外部事件挂接后,可以直接进行委托BeginInvoke(),在委托的方法中就可以直接操作界面控件了。
相关文章推荐
- [C#]事件驱动的SOCKET类
- [C#]事件驱动的SOCKET类
- 关于c#中的事件处理机制
- 关于”nodejs基于事件驱动”的思考
- 关于优化C#程序的五十种方法
- 读书整理-关于.net内置事件的驱动原理浅析
- C# 关于事件 委托的理解
- C#内部关于绑定事件Event的线程安全
- C# 事件驱动基础
- 很好的一篇关于C#事件与委托的文章
- 关于委托的一篇不错的文章(C# 中的委托和事件)
- 【面向对象语言系列】关于 C# 事件处理,你需要知道的事
- c#关于委托和事件(二)(介绍的很详细)
- NET(C#):关于进程退出的事件
- (每日心得)关于C#中委托和事件的一些认识(三)
- C# 关于委托和事件的妙文
- 关于如何设计一个基于事件驱动架构的思考
- C# 事件驱动机制
- 【20090625-01】关于C#中的自定义事件生成(转)
- 关于C# 委托(delegate)与事件(event)的用法及事例