C# 局域网内socket通信 TCP

来源:互联网 发布:ipython for windows 编辑:程序博客网 时间:2024/06/04 21:11


Socket 类

http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.aspx

判断对方正常断开连接的方法:

这里的正常断开是指调用socket.shutdown(); socket.close();关闭socket的方法。此时,另一方的socket.receive();方法会返回0个字节,即bytes = socket.receive();的bytes = 0;具体的写法参照MSDN,如下连接。

Socket.Receive 方法 (Byte[])

http://msdn.microsoft.com/zh-cn/library/8s4y8aff(v=vs.80).aspx


判断对方非正常断开:

采用异常捕获的方式处理;


对于TCP的长连接来说,接受超时和发送超时,二者默认的时间为0,意味着无限长时间等待,即阻塞。只能用于同步的长连接。

ReceiveTimeout 和SendTimeout 默认值是0即无限期等待,说更改这个值就可以设置超时时间,设置超时检测之后,系统会在超时之后自动将Connected属性设置为false,客户端链接自动断开,系统捕获异常

http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.receivetimeout(v=vs.110).aspx

socket.connect() 连接超时,是不能设置的;只能自己写;


保证TCP连接一直有效:

1、

Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

http://msdn.microsoft.com/zh-cn/library/1011kecd(VS.80).aspx


以下部分为引用于http://www.cnblogs.com/wzd24/archive/2007/05/22/755050.html#!comments

那网络异常断开原因主要有那些呢?归纳起来主要有以下两种:

1、客户端程序异常。

  对于这种情况,我们很好处理,因为客户端程序异常退出会在服务端引发ConnectionReset的Socket异常(就是WinSock2中的10054异常)。只要在服务端处理这个异常就可以了。

2、网络链路异常。

  如:网线拔出、交换机掉电、客户端机器掉电。当出现这些情况的时候服务端不会出现任何异常。这样的话上面的代码就不能处理这种情况了。对于这种情况在MSDN里面是这样处理的,我在这里贴出MSDN的原文:

如果您需要确定连接的当前状态,请进行非阻止、零字节的 Send 调用。如果该调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035),则该套接字仍然处于连接状态;否则,该套接字不再处于连接状态。

  但是我在实际应用中发现,MSDN说的这种处理方法在很多时候根本无效,无法检测出网络已经异常断开了。那我们该怎么办呢?

  我们知道,TCP有一个连接检测机制,就是如果在指定的时间内(一般为2个小时)没有数据传送,会给对端发送一个Keep-Alive数据报,使用的序列号是曾经发出的最后一个报文的最后一个字节的序列号,对端如果收到这个数据,回送一个TCP的ACK,确认这个字节已经收到,这样就知道此连接没有被断开。如果一段时间没有收到对方的响应,会进行重试,重试几次后,向对端发一个reset,然后将连接断掉。

Socket会在Keep-Alive失败后自动断开并引发Socket异常,所以你只要处理好Socket异常就行了。

  在Windows中,第一次探测是在最后一次数据发送的两个小时,然后每隔1秒探测一次,一共探测5次,如果5次都没有收到回应的话,就会断开这个连接。但两个小时对于我们的项目来说显然太长了。我们必须缩短这个时间。

2、使用心跳包

心跳包是最普遍也是最有效的方式之一。

客户端每隔一段时间向服务端发送一个数据包,来证明自己的连接有效。



0 0
原创粉丝点击