【发布时间】:2014-06-29 01:10:32
【问题描述】:
我一直在用 C# 编写一个套接字服务器程序(我的灵感来自这个post),我的问题是当客户端断开异常时“现有连接被远程主机强行关闭”在调用EndReceiveFrom()并返回0时出现,ref clientEP变为客户端常闭。我不明白为什么我的 DoReceiveFrom() 函数在没有可读的情况下被调用。我可能错过了什么。怎么了?
问题出现在那里:
int dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
完整源代码:
class UDPServer
{
private Socket serverSocket = null;
private List<EndPoint> clientList = new List<EndPoint>();
private List<Tuple<EndPoint, byte[]>> dataList = new List<Tuple<EndPoint, byte[]>>();
private byte[] byteData = new byte[1024];
private int port = 4242;
public List<Tuple<EndPoint, byte[]>> DataList
{
private set { this.dataList = value; }
get { return (this.dataList); }
}
public UDPServer(int port)
{
this.port = port;
}
public void Start()
{
this.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
this.serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.serverSocket.Bind(new IPEndPoint(IPAddress.Any, this.port));
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
}
private void DoReceiveFrom(IAsyncResult iar)
{
try
{
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
byte[] data = new byte[dataLen];
Array.Copy(this.byteData, data, dataLen);
if (!this.clientList.Any(client => client.Equals(clientEP)))
this.clientList.Add(clientEP);
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
DataList.Add(Tuple.Create(clientEP, data));
}
catch (ObjectDisposedException)
{
}
}
public void SendTo(byte[] data, EndPoint clientEP)
{
try
{
this.serverSocket.SendTo(data, clientEP);
}
catch (System.Net.Sockets.SocketException)
{
this.clientList.Remove(clientEP);
}
}
public void SendToAll(byte[] data)
{
foreach (var client in this.clientList)
{
this.SendTo(data, client);
}
}
public void Stop()
{
this.serverSocket.Close();
this.serverSocket = null;
this.dataList.Clear();
this.clientList.Clear();
}
}
例外:
An existing connection was forcibly closed by the remote host
更新: 我尝试在另一台电脑上运行我的客户端(netcat)并且不再出现异常,即使在 SendTo() 时,在我的 clientList 中删除我的客户端也是有问题的. 我还是不明白发生了什么。
【问题讨论】:
-
遇到同样的问题,你解决了吗?
-
我认为,在关闭时,调用
DoReceiveFrom是一种返回用户代码的方法,错误代码(断开连接)(可能)被存储,当调用EndReceiveFrom时,它将检查错误代码,如果错误代码 0 则将抛出异常。 (但是..就像我说的,只是猜测)我宁愿不要出现异常,断开连接不应该是异常。