Mono Socket Server 在进行大操作时会丢弃客户端
Mono Socket Server drops clients when it does big operations
单声道 3.99
我的套接字服务器 运行 在 Windows 中正常,但在 Linux/Mono 上它会丢失一个套接字。
每当服务器 运行 的操作时间超过几分之一秒时,套接字就会断开连接,但客户端偶尔会保持连接状态。客户端是 Silverlight 4,来自 Windows.
运行
更可重现的是当两个客户端连接时。第一个连接正常。第二个连接,但是当服务器 运行 进行操作时,我的服务器断开了第一个客户端的连接。发生这种情况时,第一个客户端恰好发送 0 个字节。
我的客户在一个静态列表中,因此他们不会被 GC,并且超时设置得很高。我唯一能想到的是客户端可能正在 ping 服务器,并且在 window 处理消息的时间里,它不处于接收状态。但这会使套接字变得非常脆弱。
是否有任何原因(与单声道相关或其他原因)可能导致此行为?
static void OnBeginAccept(IAsyncResult ar)
{
try
{
TcpClient _MessageClient = _MessageListener.EndAcceptTcpClient(ar);
byte[] _ReceiveBuffer = new byte[8197];
System.IO.StreamWriter streamW = new System.IO.StreamWriter(_MessageClient.GetStream());
ClientDefinition newClient = new ClientDefinition();
newClient.Socket = _MessageClient.Client;
newClient.Socket.ReceiveTimeout = 7000; newClient.Socket.SendTimeout = 7000;
newClient.username = "undefined" + clients.Count;
newClient.receiveBuffer = new byte[8197];
clients.Add(newClient);
newClient.Socket.BeginReceive(newClient.receiveBuffer, 0, 8196, SocketFlags.None, new AsyncCallback(OnReceiveComplete), newClient);
_MessageListener.BeginAcceptTcpClient(new AsyncCallback(OnBeginAccept), null);
Console.WriteLine("new client accepted");
}
catch (Exception ex) { LogError(ex); }
}
static void OnReceiveComplete(IAsyncResult ar)
{
ClientDefinition fromClient = null; //Wrapper for Socket
fromClient = (ClientDefinition)ar.AsyncState;
if (fromClient == null) return;
try
{
if (!fromClient.Socket.Connected)
{
Console.WriteLine("fromclient (" + fromClient.username + ") not connected");
CloseClient(fromClient);
return;
}
int receiveLength = 0;
receiveLength = fromClient.Socket.EndReceive(ar);
if (receiveLength == 0)
{
Console.WriteLine("Receivelength == 0");
CloseClient(fromClient);
}
SocketMessage message = null;
message = Serializer.Deserialize<SocketMessage>(fromClient.receiveBuffer);
System.Array.Clear(fromClient.receiveBuffer, 0, receiveLength);
/******Here is where I handle the messages. And when doing an operation that is 'big', a client is closed.*****/
fromClient.Socket.BeginReceive(fromClient.receiveBuffer, 0, 8196, SocketFlags.None, new AsyncCallback(OnReceiveComplete), fromClient);
}
catch (Exception ex)
{
Console.WriteLine("Exception in OnReceiveComplete: " + ex.Message + ex.StackTrace + "obj: " + ex.Source);
CloseClient(fromClient);
}
原因是我强烈引用了 Socket,而不是 TcpClient,当程序积累足够多的垃圾时,它就会处理掉NetworkStream,它因此关闭了底层套接字。此行为与 .NET 不同。通过将接受的 TcpClient 存储在静态列表中解决。
单声道 3.99 我的套接字服务器 运行 在 Windows 中正常,但在 Linux/Mono 上它会丢失一个套接字。 每当服务器 运行 的操作时间超过几分之一秒时,套接字就会断开连接,但客户端偶尔会保持连接状态。客户端是 Silverlight 4,来自 Windows.
运行更可重现的是当两个客户端连接时。第一个连接正常。第二个连接,但是当服务器 运行 进行操作时,我的服务器断开了第一个客户端的连接。发生这种情况时,第一个客户端恰好发送 0 个字节。
我的客户在一个静态列表中,因此他们不会被 GC,并且超时设置得很高。我唯一能想到的是客户端可能正在 ping 服务器,并且在 window 处理消息的时间里,它不处于接收状态。但这会使套接字变得非常脆弱。
是否有任何原因(与单声道相关或其他原因)可能导致此行为?
static void OnBeginAccept(IAsyncResult ar)
{
try
{
TcpClient _MessageClient = _MessageListener.EndAcceptTcpClient(ar);
byte[] _ReceiveBuffer = new byte[8197];
System.IO.StreamWriter streamW = new System.IO.StreamWriter(_MessageClient.GetStream());
ClientDefinition newClient = new ClientDefinition();
newClient.Socket = _MessageClient.Client;
newClient.Socket.ReceiveTimeout = 7000; newClient.Socket.SendTimeout = 7000;
newClient.username = "undefined" + clients.Count;
newClient.receiveBuffer = new byte[8197];
clients.Add(newClient);
newClient.Socket.BeginReceive(newClient.receiveBuffer, 0, 8196, SocketFlags.None, new AsyncCallback(OnReceiveComplete), newClient);
_MessageListener.BeginAcceptTcpClient(new AsyncCallback(OnBeginAccept), null);
Console.WriteLine("new client accepted");
}
catch (Exception ex) { LogError(ex); }
}
static void OnReceiveComplete(IAsyncResult ar)
{
ClientDefinition fromClient = null; //Wrapper for Socket
fromClient = (ClientDefinition)ar.AsyncState;
if (fromClient == null) return;
try
{
if (!fromClient.Socket.Connected)
{
Console.WriteLine("fromclient (" + fromClient.username + ") not connected");
CloseClient(fromClient);
return;
}
int receiveLength = 0;
receiveLength = fromClient.Socket.EndReceive(ar);
if (receiveLength == 0)
{
Console.WriteLine("Receivelength == 0");
CloseClient(fromClient);
}
SocketMessage message = null;
message = Serializer.Deserialize<SocketMessage>(fromClient.receiveBuffer);
System.Array.Clear(fromClient.receiveBuffer, 0, receiveLength);
/******Here is where I handle the messages. And when doing an operation that is 'big', a client is closed.*****/
fromClient.Socket.BeginReceive(fromClient.receiveBuffer, 0, 8196, SocketFlags.None, new AsyncCallback(OnReceiveComplete), fromClient);
}
catch (Exception ex)
{
Console.WriteLine("Exception in OnReceiveComplete: " + ex.Message + ex.StackTrace + "obj: " + ex.Source);
CloseClient(fromClient);
}
原因是我强烈引用了 Socket,而不是 TcpClient,当程序积累足够多的垃圾时,它就会处理掉NetworkStream,它因此关闭了底层套接字。此行为与 .NET 不同。通过将接受的 TcpClient 存储在静态列表中解决。