我一直在研究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 中删除我的客户端也存在问题。 我仍然不明白发生了什么。
答案 0 :(得分:0)
一切都应该如此。
这是所有异步方法的工作方式:您调用 BeginDo()并将 AsyncCallback 委托的实现传递给它(在您的例如 DoReceiveFrom )。您的实现在此之后立即开始执行 - BeginDo()不是阻塞调用。
在您的实施中,您必须调用 EndDo(),这将阻止,直到发生以下两种情况之一:您调用的对象 BeginDo( ),实际上做某事,或者它会抛出异常。正如您在客户端断开连接时所做的那样。
Async方法上的source。
整个工作需要做的是
我会在EndReceiveFrom周围添加另一个try-catch。
<强>更新强>:
private void DoReceiveFrom(IAsyncResult iar)
{
try
{
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int dataLen = 0;
byte[] data = null;
try
{
dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
data = new byte[dataLen];
Array.Copy(this.byteData, data, dataLen);
}
catch(Exception e)
{
}
finally
{
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
}
if (!this.clientList.Any(client => client.Equals(clientEP)))
this.clientList.Add(clientEP);
DataList.Add(Tuple.Create(clientEP, data));
}
catch (ObjectDisposedException)
{
}
}