以下是我参考的一点资料:
首先,Socket类的Connected属性只表示最后一次I/O操作的状态,如果这之后[连接的另一方]断开了,它还一直返回true, 除非你再通过socket来发送数据。所以通过个属性来判断是行不通的!
有人说可以用Socket.Available属性来判断,msdn中说:如果[连接的另一方]断开了,它就会抛出异常。然而,这个BUG报告(http://dam.mellis.org/2004/08/net_socket_bugs_gotchas/)却指出:msdn的说法并不完全正确,这个属性只有在少数情况下才抛出异常。所以,这一招还是行不通!
事实上,Socket.Receive()方法在[连接的另一方]断开时,它返回结果告知只读了0个字节,我们可以籍由这一点来找出答案。这个问答(http://www.dotnet247.com/247reference/msgs/36/182526.aspx)给出了好的解决方案:可以调用Socket.Poll() 方法,为该方法的第二个参数传入SelectRead 值,如果该方法返回true, 则可以再由Socket.Receive()方法的返回值来判断, 我简要的写出代码:
{
try
{
return !_client.Poll(1, SelectMode.SelectRead) && (_client.Available == 0);
}
catch (SocketException)
{
return false;
}
catch (ObjectDisposedException)
{
return false;
}
}
但是我发现参考资料上给的方法也不是很好用,因为即便是网络正常连接时,nRead的值也可能是0,比较郁闷。看来只能用频繁发送探测包的方法了。
困扰了我一天的问题,在这里做个小记。
转自:http://bbs.csdn.net/topics/290010343
Poll 方法将会检查 Socket 的状态。指定 selectMode 参数的 SelectMode..::.SelectRead,可确定 Socket 是否为可读。指定 SelectMode..::.SelectWrite,可确定 Socket 是否为可写。使用 SelectMode..::.SelectError 检测错误条件。Poll 将在指定的时段(以 microseconds 为单位)内阻止执行。如果希望无限期的等待响应,则将 microSeconds 设置为一个负整数。如果要检查多个套接字的状态,则不妨使用 Select 方法。
此方法不能检测某些类型的连接问题,例如,网络电缆中断或远程主机意外关闭。您必须尝试发送或接收数据以检测这些类型的错误。
这个是我在http://technet.microsoft.com/zh-cn/system.Net.sockets.socket.poll.aspx上看的,够权威吧,看来只能发一个特殊的东西给socket的另一方,再在对方的逻辑里写上收到的是这个特殊的东西就回发一个特殊的东西。这样才能保证socket还能用。
而且还有。poll方法是向socket里写或者读出一部分数据,这样的话,如果你其他的线程也在接收socket里的数据的话,就会接收不全了,我在做一个远程通信软件时也遇到这样的问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
private
void
timer1_Tick(
object
sender, EventArgs e)
{
if
(socket !=
null
&& socket.Connected)
{
if
(socket.Poll(1, SelectMode.SelectRead))
{
try
{
byte
[] temp =
new
byte
[1024];
int
nRead = socket.Receive(temp);
if
(nRead == 0)
{
MessageBox.Show(
"000连接已断开了,请处理"
);
}
}
catch
{
MessageBox.Show(
"连接已断开了,请处理"
);
}
}
try
{
int
ii=socket.Send(
new
byte
[1]);
}
catch
(SocketException se)
{
if
(se.ErrorCode == 10054)
// Error code for Connection reset
{
MessageBox.Show(
"连接已断开了,请处理"
);
}
else
{
MessageBox.Show(se.Message);
}
}
}
}
可以通过调用Socket对象的SetSocketOption方法设置套接字的各种选项,它有3种重载的形式: public void SetSocketOption(SetSocketOptionLevel sl,SocketOptionName sn,byte[]value) public void SetSocketOption(SetSocketOptionLevel sl,SocketOptionName sn,int value) public void SetSocketOption(SetSocketOptionLevel sl,SocketOptionName sn,object value) 其中sl定义套接字选项的类型,可选类弄有IP、Socket、Tcp、Udp。 sn指定套接字选项的值,常用的选项值。
使用方法: s.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.SendTimeout,1000); 原:至于是否有效还需测试 |