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 存储在静态列表中解决。