我一直在用C#编写套接字服务器程序(灵感来源于这篇文章),我的问题是当客户端断开连接时,调用EndReceiveFrom()返回0并出现异常“An existing connection was forcibly closed by the remote host”,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,则会抛出异常。(但是,就像我说的那样,只是猜测)我宁愿不要出现异常,断开连接不应该是异常。 - Jeroen van Langen