Mono-Socket服务器在执行大型操作时会丢弃客户端



Mono 3.99我的套接字服务器在Windows中运行良好,但在Linux/Mono上,它会丢弃一个套接字。每当服务器运行操作的时间超过几分之一秒时,套接字就会断开连接,但偶尔客户端会保持连接。客户端是Silverlight 4,并且是从Windows运行的。

更具可复制性的是当两个客户端连接时。第一个连接良好。第二个连接,但当服务器运行操作时,我的服务器会断开第一个客户端的连接。当这种情况发生时,第一个客户端发送的字节正好为0。

我把我的客户端放在一个静态列表中,这样它们就不会被GC占用,并且超时设置得很高。我唯一能想到的是,客户端可能正在ping服务器,在处理消息的时间窗口内,它不处于接收状态。但这会使插座变得极其脆弱。

是否有任何原因(与Mono相关或其他原因)可能导致这种行为?

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

最新更新