Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .netcore套接字在classic.net仍然工作时中断_C#_Sockets_.net Core - Fatal编程技术网

C# .netcore套接字在classic.net仍然工作时中断

C# .netcore套接字在classic.net仍然工作时中断,c#,sockets,.net-core,C#,Sockets,.net Core,我用经典的.net编写了客户端和服务器,通过TCP套接字进行通信。我还对许多并行连接进行了负载测试,一切正常 但是,使用.netcore的相同代码会中断。在linux上,它总是中断,客户端在尝试从流中读取数据时出现异常: 客户端套接字错误:无法从传输连接读取数据:连接超时 或者服务器也可能返回0作为要读取的字节 在Windows上。netcore客户端中断的频率较低,但有时仍会出现以下错误: 套接字错误:无法从传输连接读取数据:连接尝试失败,因为连接方未正确连接 一段时间后响应,或建立的连接失败

我用经典的.net编写了客户端和服务器,通过TCP套接字进行通信。我还对许多并行连接进行了负载测试,一切正常

但是,使用.netcore的相同代码会中断。在linux上,它总是中断,客户端在尝试从流中读取数据时出现异常:

客户端套接字错误:无法从传输连接读取数据:连接超时

或者服务器也可能返回0作为要读取的字节

在Windows上。netcore客户端中断的频率较低,但有时仍会出现以下错误:

套接字错误:无法从传输连接读取数据:连接尝试失败,因为连接方未正确连接 一段时间后响应,或建立的连接失败 因为连接的主机无法响应

.netcore 3.0

你知道为什么会这样吗

客户:

    public class TcpConnection
    {
        object _lock = new object();
        bool _is_busy = false;
        public bool TakeLock()
        {
            lock (_lock)
            {
                if (_is_busy)
                {
                    return false;
                }
                else
                {
                    _is_busy = true;
                    return true;
                }
            }
        }
        public void ReleaseLock()
        {
            _is_busy = false;
        }
        public bool Connected { get; set; }
        public string ConnError { get; set; }
        public Socket client { get; set; }
        public Stream stream { get; set; }
        public BinaryWriter bw { get; set; }
        public DateTime LastUsed { get; set; }
        public int Index { get; set; }
        public TcpConnection(string hostname, int port)
        {
            client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            SocketAsyncEventArgs connectEventArg = new SocketAsyncEventArgs();
            connectEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(ConnectedEvent);
            connectEventArg.UserToken = this;
            connectEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(hostname), port);
            var connected = client.ConnectAsync(connectEventArg);
            if (!connected)
            {
                if (connectEventArg.SocketError != SocketError.Success)
                {
                    #if (VERBOSE)
                    Console.WriteLine("Connection error (immediate)");
                    #endif
                    throw new LinqDbException("Linqdb: Connection error (immediate)");
                }
                #if (VERBOSE)
                Console.WriteLine("Connected immediately");
                #endif
                //client.NoDelay = true;
                client.ReceiveTimeout = 60000;
                client.SendTimeout = 60000;
                this.stream = new NetworkStream(client);
                this.bw = new BinaryWriter(stream);
            }
            else
            {
                int total_wait_ms = 0;
                while (!this.Connected)
                {
                    Thread.Sleep(100);

                    total_wait_ms += 100;
                    #if (VERBOSE)
                    if (total_wait_ms % 2000 == 0)
                    {
                        Console.WriteLine("Can't connect in {0} ms", total_wait_ms);
                    }
                    #endif
                }
                if (!string.IsNullOrEmpty(this.ConnError))
                {
                    throw new LinqDbException(this.ConnError + "  after " + total_wait_ms + " ms wait time");
                }
                else
                {
                    #if (VERBOSE)
                    Console.WriteLine("Connected {0} ms", total_wait_ms);
                    #endif
                }
            }
            _is_busy = true;
            LastUsed = DateTime.Now;
        }
        private void ConnectedEvent(object sender, SocketAsyncEventArgs e)
        {
            TcpConnection conn = e.UserToken as TcpConnection;
            if (e.SocketError != SocketError.Success)
            {
                #if (VERBOSE)
                Console.WriteLine("Connection error");
                #endif
                conn.ConnError = "Connection error";
                conn.Connected = true;
                return;
            }
            //e.ConnectSocket.NoDelay = true;
            e.ConnectSocket.ReceiveTimeout = 60000;
            e.ConnectSocket.SendTimeout = 60000;

            conn.stream = new NetworkStream(conn.client);
            conn.bw = new BinaryWriter(conn.stream);
            conn.ConnError = null;
            conn.Connected = true;
        }        
    }

    public class ClientSockets
    {

        const int _limit = 100;
        TcpConnection[] cons = new TcpConnection[_limit];
        object _lock = new object();
        object[] _locks = null;

        public byte[] CallServer(byte[] input, string hostname, int port, out string error_msg)
        {
            error_msg = null;
            if (_locks == null)
            {
                lock (_lock)
                {
                    if (_locks == null)
                    {
                        _locks = new object[_limit];
                        for (int i = 0; i < _limit; i++)
                        {
                            _locks[i] = new object();
                        }
                    }
                }
            }
            TcpConnection conn = null;
            while (true)
            {
                int last_index = 0;
                for (int i = _limit - 1; i >= 0; i--)
                {
                    if (cons[i] != null)
                    {
                        last_index = i;
                        break;
                    }
                }
                for (int i = 0; i < _limit; i++)
                {
                    var tmp = cons[i];
                    if (tmp != null)
                    {
                        var available = tmp.TakeLock();
                        if (!available)
                        {
                            continue;
                        }
                        else
                        {
                            if ((DateTime.Now - tmp.LastUsed).TotalSeconds > 30)
                            {
                                cons[i] = null;
                                try
                                {
                                    tmp.client.Dispose();
                                    tmp.stream.Dispose();
                                    tmp.bw.Dispose();
                                }
                                catch (Exception ex)
                                {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                                }
                                continue;
                            }
                            else
                            {
                                //ping
                                tmp.bw.Write(BitConverter.GetBytes(-3));
                                tmp.bw.Flush();

                                int numBytesRead = 0;
                                var data = new byte[1024];
                                var bad = false;
                                while (numBytesRead < 4)
                                {
                                    int read = 0;
                                    try
                                    {
                                        read = tmp.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                                    }
                                    catch (Exception ex)
                                    {
                                        //server closed connection
                                        bad = true;
                                        break;
                                    }
                                    numBytesRead += read;
                                    if (read <= 0)
                                    {
                                        //server closed connection
                                        bad = true;
                                        break;
                                    }
                                }
                                if (bad)
                                {
                                    cons[i] = null;
                                    try
                                    {
                                        tmp.client.Dispose();
                                        tmp.stream.Dispose();
                                        tmp.bw.Dispose();
                                    }
                                    catch (Exception ex)
                                    {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                                    }
                                    continue;
                                }
                                var pong = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                                if (pong != -3)
                                {
                                    cons[i] = null;
                                    try
                                    {
                                        tmp.client.Dispose();
                                        tmp.stream.Dispose();
                                        tmp.bw.Dispose();
                                    }
                                    catch (Exception ex)
                                    {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                                    }
                                    continue;
                                }

                                //socket is ok
                                conn = tmp;
                                break;
                            }

                        }
                    }
                    else
                    {
                        if (i < last_index)
                        {
                            continue;
                        }
                        if (Monitor.TryEnter(_locks[i]))
                        {
                            try
                            {
                                if (cons[i] != null)
                                {
                                    continue;
                                }
                                conn = new TcpConnection(hostname, port);
                                cons[i] = conn;
                                conn.Index = i;
                                break;
                            }
                            catch (Exception ex)
                            {
                                conn = null;
                                cons[i] = null;
                                #if (VERBOSE)
                                Console.WriteLine("Client socket creation error: " + ex.Message);
                                #endif
                                error_msg = ex.Message;
                                return BitConverter.GetBytes(-1);
                            }
                            finally
                            {
                                Monitor.Exit(_locks[i]);
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                if (conn == null)
                {
                    Thread.Sleep(150);
                    continue;
                }
                else
                {
                    break;
                }
            }

            bool error = false;
            try
            {
                var length = BitConverter.GetBytes(input.Length);
                var data = new byte[1024];
                conn.bw.Write(input);
                conn.bw.Flush();

                using (MemoryStream ms = new MemoryStream())
                {
                    int numBytesRead;
                    int total;
                    while (true)
                    {
                        numBytesRead = 0;
                        while (numBytesRead < 4)
                        {
                            int read = conn.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                            numBytesRead += read;
                            if (read <= 0)
                            {
                                throw new LinqDbException("Read <= 0: " + read);
                            }
                        }
                        numBytesRead -= 4;
                        total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                        if (total == -2)
                        {
                            #if (VERBOSE)
                            Console.WriteLine("PINGER!!!");
                            #endif
                            continue;
                        }
                        break;
                    }
                    if (numBytesRead > 0)
                    {
                        var finput = new byte[numBytesRead];
                        for (int i = 0; i < numBytesRead; i++)
                        {
                            finput[i] = data[4 + i];
                        }
                        ms.Write(finput, 0, numBytesRead);
                    }
                    total -= numBytesRead;
                    while (total > 0)
                    {
                        numBytesRead = conn.stream.Read(data, 0, data.Length);
                        if (numBytesRead <= 0)
                        {
                            throw new LinqDbException("numBytesRead <= 0: " + numBytesRead);
                        }
                        ms.Write(data, 0, numBytesRead);
                        total -= numBytesRead;
                    }
                    conn.LastUsed = DateTime.Now;
                    return ms.ToArray();
                }
            }
            catch (Exception ex)
            {
                #if (VERBOSE)
                Console.WriteLine("Client socket error: " + ex.Message);
                #endif
                error = true;
                error_msg = ex.Message;
                return BitConverter.GetBytes(-1);
            }
            finally
            {
                if (!error)
                {
                    conn.ReleaseLock();
                }
                else
                {
                    cons[conn.Index] = null;
                    try
                    {
                        conn.client.Dispose();
                        conn.stream.Dispose();
                        conn.bw.Dispose();
                    }
                    catch (Exception ex)
                    {
                        #if (VERBOSE)
                        Console.WriteLine("Disposing error:" + ex.Message);
                        #endif
                    }
                }
            }
        }
    }
服务器:

    class Pinger
    {
        public bool Done { get; set; }
        public object _lock = new object();
        public BinaryWriter bw { get; set; }
        public void Do()
        {
            try
            {
                int total_wait = 0;
                int sleep_ms = 2000;
                while (!Done)
                {
                    Thread.Sleep(sleep_ms);
                    total_wait += sleep_ms;
                    if (total_wait % 10000 == 0)
                    {
                        lock (_lock)
                        {
                            if (!Done)
                            {
                                bw.Write(BitConverter.GetBytes(-2));
                                bw.Flush();
                            }
                        }
                    }
                }
            }
            catch { return; }
        }
    }
    class ServerSockets
    {
        static Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        static string db_path = null;
        static int port = 0;
        public static void Main()
        {
            AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
            CommandHelper.ReadConfig(out db_path, out port);
            var sw = new Stopwatch();
            sw.Start();
            Console.WriteLine("Building in-memory indexes...");
            ServerLogic.Logic.ServerBuildIndexesOnStart(db_path);
            sw.Stop();
            Console.WriteLine("Done building in-memory indexes. It took: " + Math.Round(sw.ElapsedMilliseconds / 60000.0, 0) + " min.");

            Console.WriteLine("Listening on " + port);
            listener.Bind(new IPEndPoint(IPAddress.Any, port));
            listener.Listen((int)SocketOptionName.MaxConnections);


            SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
            acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
            bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
            if (!willRaiseEvent)
            {
                Service(null, acceptEventArg);
            }

            while (true)
            {
                try
                {
                    Thread.Sleep(60000);
                    #if (VERBOSE)
                    Console.WriteLine("Still kicking...");
                    #endif
                }
                catch (Exception ex)
                {
                    Console.WriteLine("BAD ERROR... " + ex.Message);
                }
            }
        }
        static void OnProcessExit(object sender, EventArgs e)
        {
            ServerLogic.Logic.Dispose();
        }
        private static void LoopToStartAccept()
        {
            SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
            acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
            bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
            if (!willRaiseEvent)
            {
                Service(null, acceptEventArg);
            }
        }
        private static void HandleBadAccept(SocketAsyncEventArgs acceptEventArgs)
        {
            #if (VERBOSE)
            Console.WriteLine("bad accept");
            #endif
            acceptEventArgs.AcceptSocket.Dispose();
        }
        private static void Service(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError != SocketError.Success)
            {
                LoopToStartAccept();
                HandleBadAccept(e);
                return;
            }

            LoopToStartAccept();


            try
            {
                using (Socket soc = e.AcceptSocket)
                {
                    var rg = new Random();
                    #if (VERBOSE)
                    Console.WriteLine("New socket: " + rg.Next(0, 1000000));
                    #endif
                    //soc.NoDelay = true;
                    soc.ReceiveTimeout = 60000;
                    soc.SendTimeout = 60000;
                    using (Stream stream = new NetworkStream(soc))
                    using (BinaryWriter bw = new BinaryWriter(stream))
                    {
                        while (true) //reuse same connection for many commands
                        {
                            byte[] data = new byte[1024];
                            using (MemoryStream ms = new MemoryStream())
                            {
                                int numBytesRead = 0;
                                while (numBytesRead < 4)
                                {
                                    int read = 0;
                                    try
                                    {
                                        read = stream.Read(data, numBytesRead, data.Length - numBytesRead);
                                    }
                                    catch (Exception ex)
                                    {
                                        //client closed connection
                                        return;
                                    }
                                    numBytesRead += read;
                                    if (read <= 0)
                                    {
                                        //throw new Exception("Read <= 0: " + read);
                                        //client closed connection
                                        return;
                                    }
                                }
                                numBytesRead -= 4;
                                var total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                                if (total == -3) //ping
                                {
                                    //pong
                                    bw.Write(BitConverter.GetBytes(-3));
                                    bw.Flush();
                                    continue;
                                }
                                if (numBytesRead > 0)
                                {
                                    var finput = new byte[numBytesRead];
                                    for (int i = 0; i < numBytesRead; i++)
                                    {
                                        finput[i] = data[4 + i];
                                    }
                                    ms.Write(finput, 0, numBytesRead);
                                }
                                total -= numBytesRead;
                                while (total > 0)
                                {
                                    numBytesRead = stream.Read(data, 0, data.Length);
                                    if (numBytesRead <= 0)
                                    {
                                        throw new Exception("numBytesRead <= 0: " + numBytesRead);
                                    }
                                    ms.Write(data, 0, numBytesRead);
                                    total -= numBytesRead;
                                }
                                var input = ms.ToArray();
                                var pinger = new Pinger()
                                {
                                    bw = bw
                                };
                                ThreadPool.QueueUserWorkItem(f => { pinger.Do(); });
                                var output = ServerLogic.Logic.Execute(input, db_path);
                                pinger.Done = true;
                                lock (pinger._lock)
                                {
                                    bw.Write(output);
                                    bw.Flush();
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
#if (VERBOSE)
                Console.WriteLine("Socket error: " + ex.Message);
#endif
                //try
                //{
                //    var rg = new Random();
                //    File.WriteAllText("sock_error_" + rg.Next() + ".txt", ex.Message + " " + ex.StackTrace + (ex.InnerException != null ? (" " + ex.InnerException.Message + " " + ex.InnerException.StackTrace) : ""));
                //}
                //catch (Exception) { }
                return;
            }
            finally
            {
                #if (VERBOSE)
                Console.WriteLine("Listener finally ");
                #endif
            }
        }
    }
编辑 完全可复制项目:

编辑 仍然没有解决方案,谁能解决这个问题,就多给500分

编辑 可能相关

我调试了您的代码,看起来问题是.NET core中的错误而不是套接字问题。从代码看,您希望发送的数据的前四个字节将包含数据的长度,但您只发送数据。这会导致获得随机数据长度,因为数据的前四个字节用作长度。在某些情况下,这比实际数据大,然后是while循环,它在等待更多永远不会到达的数据时读取数据超时

以下是客户端代码中有问题的部分:

var length = BitConverter.GetBytes(input.Length); // You prepare the length
var data = new byte[1024];
conn.bw.Write(length); // This is missing in your code so it never gets sent to the server
conn.bw.Write(input);
conn.bw.Flush();
包含修复程序的完整客户端:

public class ClientSockets
{

   const int _limit = 100;
   TcpConnection[] cons = new TcpConnection[_limit];
   object _lock = new object();
   object[] _locks = null;

   public byte[] CallServer(byte[] input, string hostname, int port, out string error_msg)
   {
      error_msg = null;
      if (_locks == null)
      {
         lock (_lock)
         {
            if (_locks == null)
            {
               _locks = new object[_limit];
               for (int i = 0; i < _limit; i++)
               {
                  _locks[i] = new object();
               }
            }
         }
      }
      TcpConnection conn = null;
      while (true)
      {
         int last_index = 0;
         for (int i = _limit - 1; i >= 0; i--)
         {
            if (cons[i] != null)
            {
               last_index = i;
               break;
            }
         }
         for (int i = 0; i < _limit; i++)
         {
            var tmp = cons[i];
            if (tmp != null)
            {
               var available = tmp.TakeLock();
               if (!available)
               {
                  continue;
               }
               else
               {
                  if ((DateTime.Now - tmp.LastUsed).TotalSeconds > 30)
                  {
                     cons[i] = null;
                     try
                     {
                        tmp.client.Dispose();
                        tmp.stream.Dispose();
                        tmp.bw.Dispose();
                     }
                     catch (Exception ex)
                     {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                     }
                     continue;
                  }
                  else
                  {
                     //ping
                     tmp.bw.Write(BitConverter.GetBytes(-3));
                     tmp.bw.Flush();

                     int numBytesRead = 0;
                     var data = new byte[1024];
                     var bad = false;
                     while (numBytesRead < 4)
                     {
                        int read = 0;
                        try
                        {
                           read = tmp.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                        }
                        catch (Exception ex)
                        {
                           //server closed connection
                           bad = true;
                           break;
                        }
                        numBytesRead += read;
                        if (read <= 0)
                        {
                           //server closed connection
                           bad = true;
                           break;
                        }
                     }
                     if (bad)
                     {
                        cons[i] = null;
                        try
                        {
                           tmp.client.Dispose();
                           tmp.stream.Dispose();
                           tmp.bw.Dispose();
                        }
                        catch (Exception ex)
                        {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                        }
                        continue;
                     }
                     var pong = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                     if (pong != -3)
                     {
                        cons[i] = null;
                        try
                        {
                           tmp.client.Dispose();
                           tmp.stream.Dispose();
                           tmp.bw.Dispose();
                        }
                        catch (Exception ex)
                        {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                        }
                        continue;
                     }

                     //socket is ok
                     conn = tmp;
                     break;
                  }

               }
            }
            else
            {
               if (i < last_index)
               {
                  continue;
               }
               if (Monitor.TryEnter(_locks[i]))
               {
                  try
                  {
                     if (cons[i] != null)
                     {
                        continue;
                     }
                     conn = new TcpConnection(hostname, port);
                     cons[i] = conn;
                     conn.Index = i;
                     break;
                  }
                  catch (Exception ex)
                  {
                     conn = null;
                     cons[i] = null;
#if (VERBOSE)
                                Console.WriteLine("Client socket creation error: " + ex.Message);
#endif
                     error_msg = ex.Message;
                     return BitConverter.GetBytes(-1);
                  }
                  finally
                  {
                     Monitor.Exit(_locks[i]);
                  }
               }
               else
               {
                  continue;
               }
            }
         }
         if (conn == null)
         {
            Thread.Sleep(150);
            continue;
         }
         else
         {
            break;
         }
      }

      bool error = false;
      try
      {
         var length = BitConverter.GetBytes(input.Length);
         var data = new byte[1024];
         conn.bw.Write(length); // Send the length first.
         conn.bw.Write(input);
         conn.bw.Flush();

         using (MemoryStream ms = new MemoryStream())
         {
            int numBytesRead;
            int total;
            while (true)
            {
               numBytesRead = 0;
               while (numBytesRead < 4)
               {
                  int read = conn.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                  numBytesRead += read;
                  if (read <= 0)
                  {
                     throw new LinqDbException("Read <= 0: " + read);
                  }
               }
               numBytesRead -= 4;
               total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
               if (total == -2)
               {
#if (VERBOSE)
                            Console.WriteLine("PINGER!!!");
#endif
                  continue;
               }
               break;
            }
            if (numBytesRead > 0)
            {
               var finput = new byte[numBytesRead];
               for (int i = 0; i < numBytesRead; i++)
               {
                  finput[i] = data[4 + i];
               }
               ms.Write(finput, 0, numBytesRead);
            }
            total -= numBytesRead;
            while (total > 0)
            {
               numBytesRead = conn.stream.Read(data, 0, data.Length);
               if (numBytesRead <= 0)
               {
                  throw new LinqDbException("numBytesRead <= 0: " + numBytesRead);
               }
               ms.Write(data, 0, numBytesRead);
               total -= numBytesRead;
            }
            conn.LastUsed = DateTime.Now;
            return ms.ToArray();
         }
      }
      catch (Exception ex)
      {
#if (VERBOSE)
                Console.WriteLine("Client socket error: " + ex.Message);
#endif
         error = true;
         error_msg = ex.Message;
         return BitConverter.GetBytes(-1);
      }
      finally
      {
         if (!error)
         {
            conn.ReleaseLock();
         }
         else
         {
            cons[conn.Index] = null;
            try
            {
               conn.client.Dispose();
               conn.stream.Dispose();
               conn.bw.Dispose();
            }
            catch (Exception ex)
            {
#if (VERBOSE)
                        Console.WriteLine("Disposing error:" + ex.Message);
#endif
            }
         }
      }
   }
}
class ServerSockets
{
   static Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

   static string db_path = null;
   static int port = 0;
   public static void Main()
   {
      AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
      CommandHelper.ReadConfig(out db_path, out port);
      var sw = new Stopwatch();
      sw.Start();
      Console.WriteLine("Building in-memory indexes...");
      ServerLogic.Logic.ServerBuildIndexesOnStart(db_path);
      sw.Stop();
      Console.WriteLine("Done building in-memory indexes. It took: " + Math.Round(sw.ElapsedMilliseconds / 60000.0, 0) + " min.");

      Console.WriteLine("Listening on " + port);
      listener.Bind(new IPEndPoint(IPAddress.Any, port));
      listener.Listen((int)SocketOptionName.MaxConnections);


      SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
      acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
      bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
      if (!willRaiseEvent)
      {
         Service(null, acceptEventArg);
      }

      while (true)
      {
         try
         {
            Thread.Sleep(60000);
#if (VERBOSE)
                    Console.WriteLine("Still kicking...");
#endif
         }
         catch (Exception ex)
         {
            Console.WriteLine("BAD ERROR... " + ex.Message);
         }
      }
   }
   static void OnProcessExit(object sender, EventArgs e)
   {
      ServerLogic.Logic.Dispose();
   }
   private static void LoopToStartAccept()
   {
      SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
      acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
      bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
      if (!willRaiseEvent)
      {
         Service(null, acceptEventArg);
      }
   }
   private static void HandleBadAccept(SocketAsyncEventArgs acceptEventArgs)
   {
#if (VERBOSE)
            Console.WriteLine("bad accept");
#endif
      acceptEventArgs.AcceptSocket.Dispose();
   }
   private static void Service(object sender, SocketAsyncEventArgs e)
   {
      if (e.SocketError != SocketError.Success)
      {
         LoopToStartAccept();
         HandleBadAccept(e);
         return;
      }

      LoopToStartAccept();


      try
      {
         using (Socket soc = e.AcceptSocket)
         {
            var rg = new Random();
#if (VERBOSE)
                    Console.WriteLine("New socket: " + rg.Next(0, 1000000));
#endif
            //soc.NoDelay = true;
            soc.ReceiveTimeout = 60000;
            soc.SendTimeout = 60000;
            using (Stream stream = new NetworkStream(soc))
            using (BinaryWriter bw = new BinaryWriter(stream))
            {
               while (true) //reuse same connection for many commands
               {
                  byte[] data = new byte[1024];
                  using (MemoryStream ms = new MemoryStream())
                  {
                     int numBytesRead = 0;
                     while (numBytesRead < 4)
                     {
                        int read = 0;
                        try
                        {
                           read = stream.Read(data, numBytesRead, data.Length - numBytesRead);
                        }
                        catch (Exception ex)
                        {
                           //client closed connection
                           return;
                        }
                        numBytesRead += read;
                        if (read <= 0)
                        {
                           //throw new Exception("Read <= 0: " + read);
                           //client closed connection
                           return;
                        }
                     }
                     numBytesRead -= 4;
                     var total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                     if (total == -3) //ping
                     {
                        //pong
                        bw.Write(BitConverter.GetBytes(-3));
                        bw.Flush();
                        continue;
                     }
                     if (numBytesRead > 0)
                     {
                        var finput = new byte[numBytesRead];
                        for (int i = 0; i < numBytesRead; i++)
                        {
                           finput[i] = data[4 + i];
                        }
                        ms.Write(finput, 0, numBytesRead);
                     }
                     total -= numBytesRead;
                     while (total > 0)
                     {
                        numBytesRead = stream.Read(data, 0, data.Length);
                        if (numBytesRead <= 0)
                        {
                           throw new Exception("numBytesRead <= 0: " + numBytesRead);
                        }
                        ms.Write(data, 0, numBytesRead);
                        total -= numBytesRead;
                     }
                     var input = ms.ToArray();
                     var pinger = new Pinger()
                     {
                        bw = bw
                     };
                     ThreadPool.QueueUserWorkItem(f => { pinger.Do(); });
                     var output = ServerLogic.Logic.Execute(input, db_path);
                     var length = BitConverter.GetBytes(output.Length);
                     pinger.Done = true;
                     lock (pinger._lock)
                     {
                        bw.Write(length);
                        bw.Write(output);
                        bw.Flush();
                     }
                  }
               }
            }
         }
      }
      catch (Exception ex)
      {
#if (VERBOSE)
                Console.WriteLine("Socket error: " + ex.Message);
#endif
         //try
         //{
         //    var rg = new Random();
         //    File.WriteAllText("sock_error_" + rg.Next() + ".txt", ex.Message + " " + ex.StackTrace + (ex.InnerException != null ? (" " + ex.InnerException.Message + " " + ex.InnerException.StackTrace) : ""));
         //}
         //catch (Exception) { }
         return;
      }
      finally
      {
#if (VERBOSE)
                Console.WriteLine("Listener finally ");
#endif
      }
   }
}
包含修复程序的完整服务器:

public class ClientSockets
{

   const int _limit = 100;
   TcpConnection[] cons = new TcpConnection[_limit];
   object _lock = new object();
   object[] _locks = null;

   public byte[] CallServer(byte[] input, string hostname, int port, out string error_msg)
   {
      error_msg = null;
      if (_locks == null)
      {
         lock (_lock)
         {
            if (_locks == null)
            {
               _locks = new object[_limit];
               for (int i = 0; i < _limit; i++)
               {
                  _locks[i] = new object();
               }
            }
         }
      }
      TcpConnection conn = null;
      while (true)
      {
         int last_index = 0;
         for (int i = _limit - 1; i >= 0; i--)
         {
            if (cons[i] != null)
            {
               last_index = i;
               break;
            }
         }
         for (int i = 0; i < _limit; i++)
         {
            var tmp = cons[i];
            if (tmp != null)
            {
               var available = tmp.TakeLock();
               if (!available)
               {
                  continue;
               }
               else
               {
                  if ((DateTime.Now - tmp.LastUsed).TotalSeconds > 30)
                  {
                     cons[i] = null;
                     try
                     {
                        tmp.client.Dispose();
                        tmp.stream.Dispose();
                        tmp.bw.Dispose();
                     }
                     catch (Exception ex)
                     {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                     }
                     continue;
                  }
                  else
                  {
                     //ping
                     tmp.bw.Write(BitConverter.GetBytes(-3));
                     tmp.bw.Flush();

                     int numBytesRead = 0;
                     var data = new byte[1024];
                     var bad = false;
                     while (numBytesRead < 4)
                     {
                        int read = 0;
                        try
                        {
                           read = tmp.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                        }
                        catch (Exception ex)
                        {
                           //server closed connection
                           bad = true;
                           break;
                        }
                        numBytesRead += read;
                        if (read <= 0)
                        {
                           //server closed connection
                           bad = true;
                           break;
                        }
                     }
                     if (bad)
                     {
                        cons[i] = null;
                        try
                        {
                           tmp.client.Dispose();
                           tmp.stream.Dispose();
                           tmp.bw.Dispose();
                        }
                        catch (Exception ex)
                        {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                        }
                        continue;
                     }
                     var pong = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                     if (pong != -3)
                     {
                        cons[i] = null;
                        try
                        {
                           tmp.client.Dispose();
                           tmp.stream.Dispose();
                           tmp.bw.Dispose();
                        }
                        catch (Exception ex)
                        {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                        }
                        continue;
                     }

                     //socket is ok
                     conn = tmp;
                     break;
                  }

               }
            }
            else
            {
               if (i < last_index)
               {
                  continue;
               }
               if (Monitor.TryEnter(_locks[i]))
               {
                  try
                  {
                     if (cons[i] != null)
                     {
                        continue;
                     }
                     conn = new TcpConnection(hostname, port);
                     cons[i] = conn;
                     conn.Index = i;
                     break;
                  }
                  catch (Exception ex)
                  {
                     conn = null;
                     cons[i] = null;
#if (VERBOSE)
                                Console.WriteLine("Client socket creation error: " + ex.Message);
#endif
                     error_msg = ex.Message;
                     return BitConverter.GetBytes(-1);
                  }
                  finally
                  {
                     Monitor.Exit(_locks[i]);
                  }
               }
               else
               {
                  continue;
               }
            }
         }
         if (conn == null)
         {
            Thread.Sleep(150);
            continue;
         }
         else
         {
            break;
         }
      }

      bool error = false;
      try
      {
         var length = BitConverter.GetBytes(input.Length);
         var data = new byte[1024];
         conn.bw.Write(length); // Send the length first.
         conn.bw.Write(input);
         conn.bw.Flush();

         using (MemoryStream ms = new MemoryStream())
         {
            int numBytesRead;
            int total;
            while (true)
            {
               numBytesRead = 0;
               while (numBytesRead < 4)
               {
                  int read = conn.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                  numBytesRead += read;
                  if (read <= 0)
                  {
                     throw new LinqDbException("Read <= 0: " + read);
                  }
               }
               numBytesRead -= 4;
               total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
               if (total == -2)
               {
#if (VERBOSE)
                            Console.WriteLine("PINGER!!!");
#endif
                  continue;
               }
               break;
            }
            if (numBytesRead > 0)
            {
               var finput = new byte[numBytesRead];
               for (int i = 0; i < numBytesRead; i++)
               {
                  finput[i] = data[4 + i];
               }
               ms.Write(finput, 0, numBytesRead);
            }
            total -= numBytesRead;
            while (total > 0)
            {
               numBytesRead = conn.stream.Read(data, 0, data.Length);
               if (numBytesRead <= 0)
               {
                  throw new LinqDbException("numBytesRead <= 0: " + numBytesRead);
               }
               ms.Write(data, 0, numBytesRead);
               total -= numBytesRead;
            }
            conn.LastUsed = DateTime.Now;
            return ms.ToArray();
         }
      }
      catch (Exception ex)
      {
#if (VERBOSE)
                Console.WriteLine("Client socket error: " + ex.Message);
#endif
         error = true;
         error_msg = ex.Message;
         return BitConverter.GetBytes(-1);
      }
      finally
      {
         if (!error)
         {
            conn.ReleaseLock();
         }
         else
         {
            cons[conn.Index] = null;
            try
            {
               conn.client.Dispose();
               conn.stream.Dispose();
               conn.bw.Dispose();
            }
            catch (Exception ex)
            {
#if (VERBOSE)
                        Console.WriteLine("Disposing error:" + ex.Message);
#endif
            }
         }
      }
   }
}
class ServerSockets
{
   static Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

   static string db_path = null;
   static int port = 0;
   public static void Main()
   {
      AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
      CommandHelper.ReadConfig(out db_path, out port);
      var sw = new Stopwatch();
      sw.Start();
      Console.WriteLine("Building in-memory indexes...");
      ServerLogic.Logic.ServerBuildIndexesOnStart(db_path);
      sw.Stop();
      Console.WriteLine("Done building in-memory indexes. It took: " + Math.Round(sw.ElapsedMilliseconds / 60000.0, 0) + " min.");

      Console.WriteLine("Listening on " + port);
      listener.Bind(new IPEndPoint(IPAddress.Any, port));
      listener.Listen((int)SocketOptionName.MaxConnections);


      SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
      acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
      bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
      if (!willRaiseEvent)
      {
         Service(null, acceptEventArg);
      }

      while (true)
      {
         try
         {
            Thread.Sleep(60000);
#if (VERBOSE)
                    Console.WriteLine("Still kicking...");
#endif
         }
         catch (Exception ex)
         {
            Console.WriteLine("BAD ERROR... " + ex.Message);
         }
      }
   }
   static void OnProcessExit(object sender, EventArgs e)
   {
      ServerLogic.Logic.Dispose();
   }
   private static void LoopToStartAccept()
   {
      SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
      acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
      bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
      if (!willRaiseEvent)
      {
         Service(null, acceptEventArg);
      }
   }
   private static void HandleBadAccept(SocketAsyncEventArgs acceptEventArgs)
   {
#if (VERBOSE)
            Console.WriteLine("bad accept");
#endif
      acceptEventArgs.AcceptSocket.Dispose();
   }
   private static void Service(object sender, SocketAsyncEventArgs e)
   {
      if (e.SocketError != SocketError.Success)
      {
         LoopToStartAccept();
         HandleBadAccept(e);
         return;
      }

      LoopToStartAccept();


      try
      {
         using (Socket soc = e.AcceptSocket)
         {
            var rg = new Random();
#if (VERBOSE)
                    Console.WriteLine("New socket: " + rg.Next(0, 1000000));
#endif
            //soc.NoDelay = true;
            soc.ReceiveTimeout = 60000;
            soc.SendTimeout = 60000;
            using (Stream stream = new NetworkStream(soc))
            using (BinaryWriter bw = new BinaryWriter(stream))
            {
               while (true) //reuse same connection for many commands
               {
                  byte[] data = new byte[1024];
                  using (MemoryStream ms = new MemoryStream())
                  {
                     int numBytesRead = 0;
                     while (numBytesRead < 4)
                     {
                        int read = 0;
                        try
                        {
                           read = stream.Read(data, numBytesRead, data.Length - numBytesRead);
                        }
                        catch (Exception ex)
                        {
                           //client closed connection
                           return;
                        }
                        numBytesRead += read;
                        if (read <= 0)
                        {
                           //throw new Exception("Read <= 0: " + read);
                           //client closed connection
                           return;
                        }
                     }
                     numBytesRead -= 4;
                     var total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                     if (total == -3) //ping
                     {
                        //pong
                        bw.Write(BitConverter.GetBytes(-3));
                        bw.Flush();
                        continue;
                     }
                     if (numBytesRead > 0)
                     {
                        var finput = new byte[numBytesRead];
                        for (int i = 0; i < numBytesRead; i++)
                        {
                           finput[i] = data[4 + i];
                        }
                        ms.Write(finput, 0, numBytesRead);
                     }
                     total -= numBytesRead;
                     while (total > 0)
                     {
                        numBytesRead = stream.Read(data, 0, data.Length);
                        if (numBytesRead <= 0)
                        {
                           throw new Exception("numBytesRead <= 0: " + numBytesRead);
                        }
                        ms.Write(data, 0, numBytesRead);
                        total -= numBytesRead;
                     }
                     var input = ms.ToArray();
                     var pinger = new Pinger()
                     {
                        bw = bw
                     };
                     ThreadPool.QueueUserWorkItem(f => { pinger.Do(); });
                     var output = ServerLogic.Logic.Execute(input, db_path);
                     var length = BitConverter.GetBytes(output.Length);
                     pinger.Done = true;
                     lock (pinger._lock)
                     {
                        bw.Write(length);
                        bw.Write(output);
                        bw.Flush();
                     }
                  }
               }
            }
         }
      }
      catch (Exception ex)
      {
#if (VERBOSE)
                Console.WriteLine("Socket error: " + ex.Message);
#endif
         //try
         //{
         //    var rg = new Random();
         //    File.WriteAllText("sock_error_" + rg.Next() + ".txt", ex.Message + " " + ex.StackTrace + (ex.InnerException != null ? (" " + ex.InnerException.Message + " " + ex.InnerException.StackTrace) : ""));
         //}
         //catch (Exception) { }
         return;
      }
      finally
      {
#if (VERBOSE)
                Console.WriteLine("Listener finally ");
#endif
      }
   }
}
作为最后的评论,我不得不说您的代码非常复杂,并且没有像其他人指出的那样遵循最佳实践。我建议您学习更多关于多线程和异步编程的知识,然后改进代码,这也将使其工作得更好、更可预测

以下是有关如何异步使用套接字的Microsoft示例以及有关如何进行异步编程的一般文档的链接:


我调试了你的代码,看起来问题是bug,而不是.NETCore中的套接字问题。从代码看,您希望发送的数据的前四个字节将包含数据的长度,但您只发送数据。这会导致获得随机数据长度,因为数据的前四个字节用作长度。在某些情况下,这比实际数据大,然后是while循环,它在等待更多永远不会到达的数据时读取数据超时

以下是客户端代码中有问题的部分:

var length = BitConverter.GetBytes(input.Length); // You prepare the length
var data = new byte[1024];
conn.bw.Write(length); // This is missing in your code so it never gets sent to the server
conn.bw.Write(input);
conn.bw.Flush();
包含修复程序的完整客户端:

public class ClientSockets
{

   const int _limit = 100;
   TcpConnection[] cons = new TcpConnection[_limit];
   object _lock = new object();
   object[] _locks = null;

   public byte[] CallServer(byte[] input, string hostname, int port, out string error_msg)
   {
      error_msg = null;
      if (_locks == null)
      {
         lock (_lock)
         {
            if (_locks == null)
            {
               _locks = new object[_limit];
               for (int i = 0; i < _limit; i++)
               {
                  _locks[i] = new object();
               }
            }
         }
      }
      TcpConnection conn = null;
      while (true)
      {
         int last_index = 0;
         for (int i = _limit - 1; i >= 0; i--)
         {
            if (cons[i] != null)
            {
               last_index = i;
               break;
            }
         }
         for (int i = 0; i < _limit; i++)
         {
            var tmp = cons[i];
            if (tmp != null)
            {
               var available = tmp.TakeLock();
               if (!available)
               {
                  continue;
               }
               else
               {
                  if ((DateTime.Now - tmp.LastUsed).TotalSeconds > 30)
                  {
                     cons[i] = null;
                     try
                     {
                        tmp.client.Dispose();
                        tmp.stream.Dispose();
                        tmp.bw.Dispose();
                     }
                     catch (Exception ex)
                     {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                     }
                     continue;
                  }
                  else
                  {
                     //ping
                     tmp.bw.Write(BitConverter.GetBytes(-3));
                     tmp.bw.Flush();

                     int numBytesRead = 0;
                     var data = new byte[1024];
                     var bad = false;
                     while (numBytesRead < 4)
                     {
                        int read = 0;
                        try
                        {
                           read = tmp.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                        }
                        catch (Exception ex)
                        {
                           //server closed connection
                           bad = true;
                           break;
                        }
                        numBytesRead += read;
                        if (read <= 0)
                        {
                           //server closed connection
                           bad = true;
                           break;
                        }
                     }
                     if (bad)
                     {
                        cons[i] = null;
                        try
                        {
                           tmp.client.Dispose();
                           tmp.stream.Dispose();
                           tmp.bw.Dispose();
                        }
                        catch (Exception ex)
                        {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                        }
                        continue;
                     }
                     var pong = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                     if (pong != -3)
                     {
                        cons[i] = null;
                        try
                        {
                           tmp.client.Dispose();
                           tmp.stream.Dispose();
                           tmp.bw.Dispose();
                        }
                        catch (Exception ex)
                        {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                        }
                        continue;
                     }

                     //socket is ok
                     conn = tmp;
                     break;
                  }

               }
            }
            else
            {
               if (i < last_index)
               {
                  continue;
               }
               if (Monitor.TryEnter(_locks[i]))
               {
                  try
                  {
                     if (cons[i] != null)
                     {
                        continue;
                     }
                     conn = new TcpConnection(hostname, port);
                     cons[i] = conn;
                     conn.Index = i;
                     break;
                  }
                  catch (Exception ex)
                  {
                     conn = null;
                     cons[i] = null;
#if (VERBOSE)
                                Console.WriteLine("Client socket creation error: " + ex.Message);
#endif
                     error_msg = ex.Message;
                     return BitConverter.GetBytes(-1);
                  }
                  finally
                  {
                     Monitor.Exit(_locks[i]);
                  }
               }
               else
               {
                  continue;
               }
            }
         }
         if (conn == null)
         {
            Thread.Sleep(150);
            continue;
         }
         else
         {
            break;
         }
      }

      bool error = false;
      try
      {
         var length = BitConverter.GetBytes(input.Length);
         var data = new byte[1024];
         conn.bw.Write(length); // Send the length first.
         conn.bw.Write(input);
         conn.bw.Flush();

         using (MemoryStream ms = new MemoryStream())
         {
            int numBytesRead;
            int total;
            while (true)
            {
               numBytesRead = 0;
               while (numBytesRead < 4)
               {
                  int read = conn.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                  numBytesRead += read;
                  if (read <= 0)
                  {
                     throw new LinqDbException("Read <= 0: " + read);
                  }
               }
               numBytesRead -= 4;
               total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
               if (total == -2)
               {
#if (VERBOSE)
                            Console.WriteLine("PINGER!!!");
#endif
                  continue;
               }
               break;
            }
            if (numBytesRead > 0)
            {
               var finput = new byte[numBytesRead];
               for (int i = 0; i < numBytesRead; i++)
               {
                  finput[i] = data[4 + i];
               }
               ms.Write(finput, 0, numBytesRead);
            }
            total -= numBytesRead;
            while (total > 0)
            {
               numBytesRead = conn.stream.Read(data, 0, data.Length);
               if (numBytesRead <= 0)
               {
                  throw new LinqDbException("numBytesRead <= 0: " + numBytesRead);
               }
               ms.Write(data, 0, numBytesRead);
               total -= numBytesRead;
            }
            conn.LastUsed = DateTime.Now;
            return ms.ToArray();
         }
      }
      catch (Exception ex)
      {
#if (VERBOSE)
                Console.WriteLine("Client socket error: " + ex.Message);
#endif
         error = true;
         error_msg = ex.Message;
         return BitConverter.GetBytes(-1);
      }
      finally
      {
         if (!error)
         {
            conn.ReleaseLock();
         }
         else
         {
            cons[conn.Index] = null;
            try
            {
               conn.client.Dispose();
               conn.stream.Dispose();
               conn.bw.Dispose();
            }
            catch (Exception ex)
            {
#if (VERBOSE)
                        Console.WriteLine("Disposing error:" + ex.Message);
#endif
            }
         }
      }
   }
}
class ServerSockets
{
   static Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

   static string db_path = null;
   static int port = 0;
   public static void Main()
   {
      AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
      CommandHelper.ReadConfig(out db_path, out port);
      var sw = new Stopwatch();
      sw.Start();
      Console.WriteLine("Building in-memory indexes...");
      ServerLogic.Logic.ServerBuildIndexesOnStart(db_path);
      sw.Stop();
      Console.WriteLine("Done building in-memory indexes. It took: " + Math.Round(sw.ElapsedMilliseconds / 60000.0, 0) + " min.");

      Console.WriteLine("Listening on " + port);
      listener.Bind(new IPEndPoint(IPAddress.Any, port));
      listener.Listen((int)SocketOptionName.MaxConnections);


      SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
      acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
      bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
      if (!willRaiseEvent)
      {
         Service(null, acceptEventArg);
      }

      while (true)
      {
         try
         {
            Thread.Sleep(60000);
#if (VERBOSE)
                    Console.WriteLine("Still kicking...");
#endif
         }
         catch (Exception ex)
         {
            Console.WriteLine("BAD ERROR... " + ex.Message);
         }
      }
   }
   static void OnProcessExit(object sender, EventArgs e)
   {
      ServerLogic.Logic.Dispose();
   }
   private static void LoopToStartAccept()
   {
      SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
      acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
      bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
      if (!willRaiseEvent)
      {
         Service(null, acceptEventArg);
      }
   }
   private static void HandleBadAccept(SocketAsyncEventArgs acceptEventArgs)
   {
#if (VERBOSE)
            Console.WriteLine("bad accept");
#endif
      acceptEventArgs.AcceptSocket.Dispose();
   }
   private static void Service(object sender, SocketAsyncEventArgs e)
   {
      if (e.SocketError != SocketError.Success)
      {
         LoopToStartAccept();
         HandleBadAccept(e);
         return;
      }

      LoopToStartAccept();


      try
      {
         using (Socket soc = e.AcceptSocket)
         {
            var rg = new Random();
#if (VERBOSE)
                    Console.WriteLine("New socket: " + rg.Next(0, 1000000));
#endif
            //soc.NoDelay = true;
            soc.ReceiveTimeout = 60000;
            soc.SendTimeout = 60000;
            using (Stream stream = new NetworkStream(soc))
            using (BinaryWriter bw = new BinaryWriter(stream))
            {
               while (true) //reuse same connection for many commands
               {
                  byte[] data = new byte[1024];
                  using (MemoryStream ms = new MemoryStream())
                  {
                     int numBytesRead = 0;
                     while (numBytesRead < 4)
                     {
                        int read = 0;
                        try
                        {
                           read = stream.Read(data, numBytesRead, data.Length - numBytesRead);
                        }
                        catch (Exception ex)
                        {
                           //client closed connection
                           return;
                        }
                        numBytesRead += read;
                        if (read <= 0)
                        {
                           //throw new Exception("Read <= 0: " + read);
                           //client closed connection
                           return;
                        }
                     }
                     numBytesRead -= 4;
                     var total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                     if (total == -3) //ping
                     {
                        //pong
                        bw.Write(BitConverter.GetBytes(-3));
                        bw.Flush();
                        continue;
                     }
                     if (numBytesRead > 0)
                     {
                        var finput = new byte[numBytesRead];
                        for (int i = 0; i < numBytesRead; i++)
                        {
                           finput[i] = data[4 + i];
                        }
                        ms.Write(finput, 0, numBytesRead);
                     }
                     total -= numBytesRead;
                     while (total > 0)
                     {
                        numBytesRead = stream.Read(data, 0, data.Length);
                        if (numBytesRead <= 0)
                        {
                           throw new Exception("numBytesRead <= 0: " + numBytesRead);
                        }
                        ms.Write(data, 0, numBytesRead);
                        total -= numBytesRead;
                     }
                     var input = ms.ToArray();
                     var pinger = new Pinger()
                     {
                        bw = bw
                     };
                     ThreadPool.QueueUserWorkItem(f => { pinger.Do(); });
                     var output = ServerLogic.Logic.Execute(input, db_path);
                     var length = BitConverter.GetBytes(output.Length);
                     pinger.Done = true;
                     lock (pinger._lock)
                     {
                        bw.Write(length);
                        bw.Write(output);
                        bw.Flush();
                     }
                  }
               }
            }
         }
      }
      catch (Exception ex)
      {
#if (VERBOSE)
                Console.WriteLine("Socket error: " + ex.Message);
#endif
         //try
         //{
         //    var rg = new Random();
         //    File.WriteAllText("sock_error_" + rg.Next() + ".txt", ex.Message + " " + ex.StackTrace + (ex.InnerException != null ? (" " + ex.InnerException.Message + " " + ex.InnerException.StackTrace) : ""));
         //}
         //catch (Exception) { }
         return;
      }
      finally
      {
#if (VERBOSE)
                Console.WriteLine("Listener finally ");
#endif
      }
   }
}
包含修复程序的完整服务器:

public class ClientSockets
{

   const int _limit = 100;
   TcpConnection[] cons = new TcpConnection[_limit];
   object _lock = new object();
   object[] _locks = null;

   public byte[] CallServer(byte[] input, string hostname, int port, out string error_msg)
   {
      error_msg = null;
      if (_locks == null)
      {
         lock (_lock)
         {
            if (_locks == null)
            {
               _locks = new object[_limit];
               for (int i = 0; i < _limit; i++)
               {
                  _locks[i] = new object();
               }
            }
         }
      }
      TcpConnection conn = null;
      while (true)
      {
         int last_index = 0;
         for (int i = _limit - 1; i >= 0; i--)
         {
            if (cons[i] != null)
            {
               last_index = i;
               break;
            }
         }
         for (int i = 0; i < _limit; i++)
         {
            var tmp = cons[i];
            if (tmp != null)
            {
               var available = tmp.TakeLock();
               if (!available)
               {
                  continue;
               }
               else
               {
                  if ((DateTime.Now - tmp.LastUsed).TotalSeconds > 30)
                  {
                     cons[i] = null;
                     try
                     {
                        tmp.client.Dispose();
                        tmp.stream.Dispose();
                        tmp.bw.Dispose();
                     }
                     catch (Exception ex)
                     {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                     }
                     continue;
                  }
                  else
                  {
                     //ping
                     tmp.bw.Write(BitConverter.GetBytes(-3));
                     tmp.bw.Flush();

                     int numBytesRead = 0;
                     var data = new byte[1024];
                     var bad = false;
                     while (numBytesRead < 4)
                     {
                        int read = 0;
                        try
                        {
                           read = tmp.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                        }
                        catch (Exception ex)
                        {
                           //server closed connection
                           bad = true;
                           break;
                        }
                        numBytesRead += read;
                        if (read <= 0)
                        {
                           //server closed connection
                           bad = true;
                           break;
                        }
                     }
                     if (bad)
                     {
                        cons[i] = null;
                        try
                        {
                           tmp.client.Dispose();
                           tmp.stream.Dispose();
                           tmp.bw.Dispose();
                        }
                        catch (Exception ex)
                        {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                        }
                        continue;
                     }
                     var pong = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                     if (pong != -3)
                     {
                        cons[i] = null;
                        try
                        {
                           tmp.client.Dispose();
                           tmp.stream.Dispose();
                           tmp.bw.Dispose();
                        }
                        catch (Exception ex)
                        {
#if (VERBOSE)
                                    Console.WriteLine("Disposing error:" + ex.Message);
#endif
                        }
                        continue;
                     }

                     //socket is ok
                     conn = tmp;
                     break;
                  }

               }
            }
            else
            {
               if (i < last_index)
               {
                  continue;
               }
               if (Monitor.TryEnter(_locks[i]))
               {
                  try
                  {
                     if (cons[i] != null)
                     {
                        continue;
                     }
                     conn = new TcpConnection(hostname, port);
                     cons[i] = conn;
                     conn.Index = i;
                     break;
                  }
                  catch (Exception ex)
                  {
                     conn = null;
                     cons[i] = null;
#if (VERBOSE)
                                Console.WriteLine("Client socket creation error: " + ex.Message);
#endif
                     error_msg = ex.Message;
                     return BitConverter.GetBytes(-1);
                  }
                  finally
                  {
                     Monitor.Exit(_locks[i]);
                  }
               }
               else
               {
                  continue;
               }
            }
         }
         if (conn == null)
         {
            Thread.Sleep(150);
            continue;
         }
         else
         {
            break;
         }
      }

      bool error = false;
      try
      {
         var length = BitConverter.GetBytes(input.Length);
         var data = new byte[1024];
         conn.bw.Write(length); // Send the length first.
         conn.bw.Write(input);
         conn.bw.Flush();

         using (MemoryStream ms = new MemoryStream())
         {
            int numBytesRead;
            int total;
            while (true)
            {
               numBytesRead = 0;
               while (numBytesRead < 4)
               {
                  int read = conn.stream.Read(data, numBytesRead, data.Length - numBytesRead);
                  numBytesRead += read;
                  if (read <= 0)
                  {
                     throw new LinqDbException("Read <= 0: " + read);
                  }
               }
               numBytesRead -= 4;
               total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
               if (total == -2)
               {
#if (VERBOSE)
                            Console.WriteLine("PINGER!!!");
#endif
                  continue;
               }
               break;
            }
            if (numBytesRead > 0)
            {
               var finput = new byte[numBytesRead];
               for (int i = 0; i < numBytesRead; i++)
               {
                  finput[i] = data[4 + i];
               }
               ms.Write(finput, 0, numBytesRead);
            }
            total -= numBytesRead;
            while (total > 0)
            {
               numBytesRead = conn.stream.Read(data, 0, data.Length);
               if (numBytesRead <= 0)
               {
                  throw new LinqDbException("numBytesRead <= 0: " + numBytesRead);
               }
               ms.Write(data, 0, numBytesRead);
               total -= numBytesRead;
            }
            conn.LastUsed = DateTime.Now;
            return ms.ToArray();
         }
      }
      catch (Exception ex)
      {
#if (VERBOSE)
                Console.WriteLine("Client socket error: " + ex.Message);
#endif
         error = true;
         error_msg = ex.Message;
         return BitConverter.GetBytes(-1);
      }
      finally
      {
         if (!error)
         {
            conn.ReleaseLock();
         }
         else
         {
            cons[conn.Index] = null;
            try
            {
               conn.client.Dispose();
               conn.stream.Dispose();
               conn.bw.Dispose();
            }
            catch (Exception ex)
            {
#if (VERBOSE)
                        Console.WriteLine("Disposing error:" + ex.Message);
#endif
            }
         }
      }
   }
}
class ServerSockets
{
   static Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

   static string db_path = null;
   static int port = 0;
   public static void Main()
   {
      AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
      CommandHelper.ReadConfig(out db_path, out port);
      var sw = new Stopwatch();
      sw.Start();
      Console.WriteLine("Building in-memory indexes...");
      ServerLogic.Logic.ServerBuildIndexesOnStart(db_path);
      sw.Stop();
      Console.WriteLine("Done building in-memory indexes. It took: " + Math.Round(sw.ElapsedMilliseconds / 60000.0, 0) + " min.");

      Console.WriteLine("Listening on " + port);
      listener.Bind(new IPEndPoint(IPAddress.Any, port));
      listener.Listen((int)SocketOptionName.MaxConnections);


      SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
      acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
      bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
      if (!willRaiseEvent)
      {
         Service(null, acceptEventArg);
      }

      while (true)
      {
         try
         {
            Thread.Sleep(60000);
#if (VERBOSE)
                    Console.WriteLine("Still kicking...");
#endif
         }
         catch (Exception ex)
         {
            Console.WriteLine("BAD ERROR... " + ex.Message);
         }
      }
   }
   static void OnProcessExit(object sender, EventArgs e)
   {
      ServerLogic.Logic.Dispose();
   }
   private static void LoopToStartAccept()
   {
      SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
      acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
      bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
      if (!willRaiseEvent)
      {
         Service(null, acceptEventArg);
      }
   }
   private static void HandleBadAccept(SocketAsyncEventArgs acceptEventArgs)
   {
#if (VERBOSE)
            Console.WriteLine("bad accept");
#endif
      acceptEventArgs.AcceptSocket.Dispose();
   }
   private static void Service(object sender, SocketAsyncEventArgs e)
   {
      if (e.SocketError != SocketError.Success)
      {
         LoopToStartAccept();
         HandleBadAccept(e);
         return;
      }

      LoopToStartAccept();


      try
      {
         using (Socket soc = e.AcceptSocket)
         {
            var rg = new Random();
#if (VERBOSE)
                    Console.WriteLine("New socket: " + rg.Next(0, 1000000));
#endif
            //soc.NoDelay = true;
            soc.ReceiveTimeout = 60000;
            soc.SendTimeout = 60000;
            using (Stream stream = new NetworkStream(soc))
            using (BinaryWriter bw = new BinaryWriter(stream))
            {
               while (true) //reuse same connection for many commands
               {
                  byte[] data = new byte[1024];
                  using (MemoryStream ms = new MemoryStream())
                  {
                     int numBytesRead = 0;
                     while (numBytesRead < 4)
                     {
                        int read = 0;
                        try
                        {
                           read = stream.Read(data, numBytesRead, data.Length - numBytesRead);
                        }
                        catch (Exception ex)
                        {
                           //client closed connection
                           return;
                        }
                        numBytesRead += read;
                        if (read <= 0)
                        {
                           //throw new Exception("Read <= 0: " + read);
                           //client closed connection
                           return;
                        }
                     }
                     numBytesRead -= 4;
                     var total = BitConverter.ToInt32(new byte[4] { data[0], data[1], data[2], data[3] }, 0);
                     if (total == -3) //ping
                     {
                        //pong
                        bw.Write(BitConverter.GetBytes(-3));
                        bw.Flush();
                        continue;
                     }
                     if (numBytesRead > 0)
                     {
                        var finput = new byte[numBytesRead];
                        for (int i = 0; i < numBytesRead; i++)
                        {
                           finput[i] = data[4 + i];
                        }
                        ms.Write(finput, 0, numBytesRead);
                     }
                     total -= numBytesRead;
                     while (total > 0)
                     {
                        numBytesRead = stream.Read(data, 0, data.Length);
                        if (numBytesRead <= 0)
                        {
                           throw new Exception("numBytesRead <= 0: " + numBytesRead);
                        }
                        ms.Write(data, 0, numBytesRead);
                        total -= numBytesRead;
                     }
                     var input = ms.ToArray();
                     var pinger = new Pinger()
                     {
                        bw = bw
                     };
                     ThreadPool.QueueUserWorkItem(f => { pinger.Do(); });
                     var output = ServerLogic.Logic.Execute(input, db_path);
                     var length = BitConverter.GetBytes(output.Length);
                     pinger.Done = true;
                     lock (pinger._lock)
                     {
                        bw.Write(length);
                        bw.Write(output);
                        bw.Flush();
                     }
                  }
               }
            }
         }
      }
      catch (Exception ex)
      {
#if (VERBOSE)
                Console.WriteLine("Socket error: " + ex.Message);
#endif
         //try
         //{
         //    var rg = new Random();
         //    File.WriteAllText("sock_error_" + rg.Next() + ".txt", ex.Message + " " + ex.StackTrace + (ex.InnerException != null ? (" " + ex.InnerException.Message + " " + ex.InnerException.StackTrace) : ""));
         //}
         //catch (Exception) { }
         return;
      }
      finally
      {
#if (VERBOSE)
                Console.WriteLine("Listener finally ");
#endif
      }
   }
}
作为最后的评论,我不得不说您的代码非常复杂,并且没有像其他人指出的那样遵循最佳实践。我建议您学习更多关于多线程和异步编程的知识,然后改进代码,这也将使其工作得更好、更可预测

以下是有关如何异步使用套接字的Microsoft示例以及有关如何进行异步编程的一般文档的链接:


首先让我说,代码非常难理解。不仅在一个方法中会发生很多事情,还需要处理线程和大量锁。这使得事情变得异常复杂,很难精确地确定发生了什么

这就像大海捞针一样。除了由于超时、螺纹和锁定机构不断移动针头而导致的百倍恶化

我在Windows10机器上运行了这个项目,Visual Studio 2019 Preview 16.4.0 Preview 2.0和.NET Core runtime 3.1.0-preview1目标框架为3.0

让我声明一件事,您已经将客户端和服务器的接收/设置超时设置为60000。我不能用这个复制你的错误。因为这个超时值太大了,所有的事情最终都会在超时发生之前完成

为了重现您的错误,我已大大缩短了超时时间:

//文件:ClientLib.cs //方法:ConnectedEvent。。。 //第114-115行 e、 ConnectSocket.ReceiveTimeout=1000; //如果将其进一步降低,则错误会成倍增加。 上面给出了大约5个错误,由于Pinger被实例化的代码,这些错误再次发生:

//文件:Server\Program.cs //方法:服务。。。 Thread.Sleeprandom.next1001000; 在上述情况下,也会发生以下情况:

ThreadPool.QueueUserWorkItemf=>{pinger.Do;}; 服务器使用线程池,可以在其上并发处理8个操作1。不仅在建立套接字连接时使用ThreadPool,而且在创建ThreadPool.Q时也使用ThreadPool ueueUserWorkItem

这意味着当客户机开始尝试建立大量连接时会有很大的麻烦。因为这也会导致超时

增加线程池中线程的一种方法:

公共静态真空总管 { int w,c=0; ThreadPool.GetMinThreadsout w,out c; WriteLine$ThreadPool max:{w}工作线程{c}完成线程; ThreadPool.SetMinThreads100,100; ThreadPool.GetMinThreadsout w,out c; WriteLine$ThreadPool max:{w}工作线程{c}完成线程; ///其他代码。。。 } 但实际上,只要去掉这两条线就能解决问题:

var random=新随机变量; Thread.Sleeprandom.next1001000;
1这可能因机器而异,请参阅。您可以使用在您的机器上进行检查。

首先让我说,代码非常难以理解。不仅在一个方法中会发生很多事情,还需要处理线程和大量锁。这使得事情变得异常复杂,很难精确地确定发生了什么

这就像大海捞针一样。除了由于超时、螺纹和锁定机构不断移动针头而导致的百倍恶化

我在Windows10机器上运行了这个项目,Visual Studio 2019 Preview 16.4.0 Preview 2.0和.NET Core runtime 3.1.0-preview1目标框架为3.0

让我声明一件事,您已经将客户端和服务器的接收/设置超时设置为60000。我不能用这个复制你的错误。因为这个超时值太大了,所有的事情最终都会在超时发生之前完成

为了重现您的错误,我已大大缩短了超时时间:

//文件:ClientLib.cs //方法:ConnectedEvent。。。 //第114-115行 e、 ConnectSocket.ReceiveTimeout=1000; //如果将其进一步降低,则错误会成倍增加。 上面给出了大约5个错误,由于Pinger被实例化的代码,这些错误再次发生:

//文件:Server\Program.cs //方法:服务。。。 Thread.Sleeprandom.next1001000; 在上述情况下,也会发生以下情况:

ThreadPool.QueueUserWorkItemf=>{pinger.Do;}; 服务器使用线程池,可以在其上并发处理8个操作1。不仅在建立套接字连接时使用线程池,而且在执行线程池时也使用线程池。QueueUserWorkItem

这意味着当客户机开始尝试建立大量连接时会有很大的麻烦。因为这也会导致超时

增加线程池中线程的一种方法:

公共静态真空总管 { int w,c=0; ThreadPool.GetMinThreadsout w,out c; WriteLine$ThreadPool max:{w}工作线程{c}完成线程; ThreadPool.SetMinThreads100,100; ThreadPool.GetMinThreadsout w,out c; WriteLine$ThreadPool max:{w}工作线程{c}完成线程; ///其他代码。。。 } 但实际上,只要去掉这两条线就能解决问题:

var random=新随机变量; Thread.Sleeprandom.next1001000;
1这可能因机器而异,请参阅。您可以在您的机器上使用进行检查。

幸运的是,仅使用两个并行线程就重现了此问题。服务器部分出现问题:

private static void LoopToStartAccept()
{
    SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
    acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
    bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
    if (!willRaiseEvent)
    {
        Service(null, acceptEventArg);
    }
}
Servicenull,acceptEventArg;阻塞的响应套接字。改成

Task.Run=>Servicenull,acceptEventArg

解决了这个问题。但不知道为什么它在Windows上工作


按照@AlesD的建议,将客户端中的连接更改为同步也解决了一些其他问题。

幸运的是,只有两个并行线程,问题再次出现。服务器部分出现问题:

private static void LoopToStartAccept()
{
    SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
    acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Service);
    bool willRaiseEvent = listener.AcceptAsync(acceptEventArg);
    if (!willRaiseEvent)
    {
        Service(null, acceptEventArg);
    }
}
Servicenull,acceptEventArg;阻塞的响应套接字。改成

Task.Run=>Servicenull,acceptEventArg

解决了这个问题。但不知道为什么它在Windows上工作


按照@AlesD的建议,将客户端中的连接更改为同步也解决了一些其他问题。

有两件事:第一,在您的类中有一些类型我无法解析。例如,ServerLogic。将您的代码粘贴到两个新的.net核心项目中,一个用于服务器,另一个用于客户端,您将明白我的意思。其次,在锁定的周围有一种明确的代码味道……我几乎可以肯定这就是问题的根源:锁定实例变量是第一件看起来可疑的事情。考虑把锁对象静态化,看看它是否神奇地解决了问题。还有,有一个方法,而不是处置,处置你持有的东西…嗯。只是说,什么是LinqDbException?什么是CommandHelper?什么是服务器逻辑?你为什么要写这个catch{return;}!在很多地方,您可以捕获异常,如果定义了VERBOSE,则将异常写入控制台,否则忽略异常!看起来很有可能抛出了一个信息异常,而它只是被忽略了,前提是此时的异常必须是x。

例如,此行的任何异常read=stream.Readdata,numbytsread,data.Length-numbytsread;假定表示连接已关闭。@Jodrell LinqdbeException、CommandHelper、ServerLogic不相关,服务器逻辑只是做一些IO工作。尽管有许多有效的观点,但我们还是要看一看。有两件事:第一,在你们的类中,有一些类型我无法解析。例如,ServerLogic。将您的代码粘贴到两个新的.net核心项目中,一个用于服务器,另一个用于客户端,您将明白我的意思。其次,在锁定的周围有一种明确的代码味道……我几乎可以肯定这就是问题的根源:锁定实例变量是第一件看起来可疑的事情。考虑把锁对象静态化,看看它是否神奇地解决了问题。还有,有一个方法,而不是处置,处置你持有的东西…嗯。只是说,什么是LinqDbException?什么是CommandHelper?什么是服务器逻辑?你为什么要写这个catch{return;}!在很多地方,您可以捕获异常,如果定义了VERBOSE,则将异常写入控制台,否则忽略异常!看起来很有可能抛出了一个信息异常,而它只是被忽略了,前提是此时的异常必须是x。例如,此行的任何异常read=stream.Readdata,numbytsread,data.Length-numbytsread;假定表示连接已关闭。@Jodrell LinqdbeException、CommandHelper、ServerLogic不相关,服务器逻辑只是做一些IO工作。虽然有很多有效的观点,但我会看一看。如果真的那么简单。。。不过捕捉得不错-长度已经添加到clientsocket调用的参数中,并且从server.execute返回-代码未显示。我已经做了一个独立的项目来演示这个问题:在尝试了您的示例之后,它显示Linux中存在一个问题。从我的调试来看,问题似乎出在客户端而不是服务器上。对我来说,ConnectAsync行为异常,在某些情况下从不返回任何连接事件,服务器显示它收到了连接。我尝试用同步连接代替它,它工作得更好,但在某些连接上仍然超时。当我有时间的时候,我会尝试做更多的研究。虽然考虑到你必须处理大量的设计错误和代码,答案非常好,但异常处理仍然是我最讨厌的。这段代码捕获异常,这是异常处理的主要问题。它将捕获致命的异常和您永远不应该捕获的异常。我有两篇关于这个主题的文章,在这种情况下我会把它们联系起来:|是的,代码很混乱。稍后我将尝试此解决方案,我想知道它是否与此bug有关。我已经创建了一个代码重构示例,以便它使用任务和异步/等待。如果您对将来改进代码感兴趣,这可能会对您有所帮助。检查我的电脑。我知道已经很晚了,但这是一个有趣的练习。如果那是那么容易。。。不过捕捉得不错-长度已经添加到clientsocket调用的参数中,并且从server.execute返回-代码未显示。我已经做了一个独立的项目来演示这个问题:在尝试了您的示例之后,它显示Linux中存在一个问题。从我的调试来看,问题似乎出在客户端而不是服务器上。对我来说,ConnectAsync行为异常,在某些情况下从不返回任何连接事件,服务器显示它收到了连接。我尝试用同步连接代替它,它工作得更好,但在某些连接上仍然超时。当我有时间的时候,我会尝试做更多的研究。虽然考虑到你必须处理大量的设计错误和代码,答案非常好,但异常处理仍然是我最讨厌的。这段代码捕获异常,这是异常处理的主要问题。它将捕获致命的异常和您永远不应该捕获的异常。我有两篇关于这个主题的文章,在这种情况下我会把它们联系起来:|是的,代码很混乱。稍后我将尝试此解决方案,我想知道它是否与此bug有关。我已经创建了一个代码重构示例,以便它使用任务和异步/等待。如果您对将来改进代码感兴趣,这可能会对您有所帮助。检查我的电脑。我知道已经很晚了,但这是一个有趣的练习。在windows 10上,它可以正常工作,问题只发生在linux机器上。var random=新随机变量;Thread.Sleeprandom.next1001000;正在模拟在server.execute中完成的工作,需要类似的时间,或者可能需要10倍以上的时间。我试过在linux上设置最小工作线程-同样的问题。@renaha,好的,明白了。您需要在linux机器上同时运行客户端和服务器吗?是的。我还尝试了windows上的服务器,linux上的客户端,但同样失败了。所以客户端至少需要在linux上。@ren好的,很抱歉我误解了这一部分以及Thread.Sleep部分。我明天会试试那个装置。什么样的发行版有关系吗?我在ubuntu 19.10上运行,但我想它与windows 10无关,因为它正在运行
实际上,这个问题只发生在linux机器上。var random=新随机变量;Thread.Sleeprandom.next1001000;正在模拟在server.execute中完成的工作,需要类似的时间,或者可能需要10倍以上的时间。我试过在linux上设置最小工作线程-同样的问题。@renaha,好的,明白了。您需要在linux机器上同时运行客户端和服务器吗?是的。我还尝试了windows上的服务器,linux上的客户端,但同样失败了。所以客户端至少需要在linux上。@ren好的,很抱歉我误解了这一部分以及Thread.Sleep部分。我明天会试试那个装置。什么样的发行版有关系吗?我在ubuntu 19.10上运行,但我想这无关紧要