为什么我的 .NET Core 服务器应用程序在 Ubuntu 中不接受连接,但在 Windows 中工作正常?

Why isn't my .NET Core server app accepting connections in Ubuntu, but works fine in Windows?

所以,我基本上有一个服务器和一个客户端。

服务器是一个 .NET Core 2.2 控制台应用程序,它监听传入的连接,一旦连接打开,读取请求,从 MySQL 数据库中提取一些数据,并将其发送回客户端.

客户端是一个 Xamarin Forms 应用程序,它将这些请求发送到服务器。没什么复杂的。

现在,如果我 运行 我本地 Windows 机器上的服务器,它将开始侦听分配的端口并正确接受请求并发送响应。然而,当我将它部署到 Ubuntu 19.04 机器上时 运行 这个服务器应用程序,它根本看不到传入的连接。

当然,我确定这不是网络问题,我尝试 netcat ( nc -l PORT ) 相关端口,它正在接收正确的数据。

这是我的服务器代码:

    public static class Server
    {
        public static Dictionary<string, Session> Sessions { get; private set; } = new Dictionary<string, Session>();

        public static int Main(string[] args)
        {
            return RunServer();
        }

        private static int RunServer()
        {
            var listener = new TcpListener(IPAddress.Loopback, ServerConfig.Port);
            int errorCode = 0;

            try
            {
                listener.Start();
                Console.WriteLine("Server running - listening to " + ServerConfig.Port + " ..."); // this is printed in Ubuntu

                while (true)
                {
                    var clientTask = listener.AcceptTcpClientAsync();

                    if (clientTask.Result != null)
                    {
                        using (TcpClient tcpClient = clientTask.Result)
                        {
                            // This line is printed in Windows/localhost, but not on the Ubuntu production machine
                            Console.WriteLine("Connected to {0}", (tcpClient.Client.RemoteEndPoint as IPEndPoint).Address);

                            string data;
                            string cmd;
                            string[] parameters;
                            string response = null;
                            NetworkStream stream = tcpClient.GetStream();

                            data = ReceiveRemoteMessage(stream); // See below

                            if (string.IsNullOrWhiteSpace(data))
                                continue;

                            parameters = data.Split(' ');
                            cmd = parameters[0];

                            try
                            {
                                // Note: the CommunicationManager class that actually processes the requests is not relevant to this question, so it's not included
                                string methodName = "Manage" + cmd + "Request";
                                var argList = new List<object>();
                                var i = 0;
                                foreach(object par in parameters)
                                {
                                    i++;
                                    if (i == 1)
                                        continue;

                                    argList.Add(par);
                                }
                                object[] args = argList.ToArray();
                                response = (string) typeof(CommunicationManager).GetMethod(methodName).Invoke(null, args);
                            }

                            catch (Exception e)
                            {
                                if (e is AmbiguousMatchException ||
                                    e is ArgumentNullException ||
                                    e is TargetException ||
                                    e is ArgumentException ||
                                    e is TargetInvocationException ||
                                    e is TargetParameterCountException ||
                                    e is MethodAccessException ||
                                    e is InvalidOperationException ||
                                    e is NotSupportedException)
                                {
                                    response = ServerResponse.InvalidRequest; // ServerResponse is a static class with read-only static string fields
                                }
                                else
                                {
                                    response = ServerResponse.GenericException;
                                }
                            }

                            if (!string.IsNullOrWhiteSpace(response))
                            {
                                SendSocketMessage(stream, response);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                errorCode = 1;
            }
            finally
            {
                listener.Stop();
            }

            Console.WriteLine($"\nExit code: {errorCode}\nPress any key to terminate.");
            Console.ReadKey();
            return errorCode;
        }

        private static void SendSocketMessage(NetworkStream stream, string message)
        {
            var encryptedMsg = Encrypt.EncryptString(message);
            stream.Write(Encoding.UTF8.GetBytes(encryptedMsg));
        }

        private static string ReceiveRemoteMessage(NetworkStream stream)
        {
            const int bufferSize = 1024;
            byte[] bytes;
            string data = string.Empty;

            while (true)
            {
                bytes = new byte[bufferSize];
                int bytesReceived = stream.Read(bytes);

                string utfString = Encoding.UTF8.GetString(bytes, 0, bytesReceived);

                if (string.IsNullOrEmpty(utfString))
                    break;

                data += utfString;

                if (bytesReceived < bufferSize)
                    break;
            }
            var decryptedMsg = Encrypt.DecryptString(data);
            return decryptedMsg;
        }
    }

这是我的客户端代码,用于 Xamarin (Mono)

public static string SendServerRequest(string request)
        {
            //
            try
            {
                TcpClient client = new TcpClient();
                client.ConnectAsync(ServerConfig.Hostname, ServerConfig.Port).Wait();

                NetworkStream stream = client.GetStream();

                var encryptedRequest = Encrypt.EncryptString(request);
                var sentBytes = Encoding.UTF8.GetBytes(encryptedRequest);
                stream.Write(sentBytes, 0, sentBytes.Length);

                const int bufferSize = 1024;
                byte[] bytes;
                string data = string.Empty;
                int totalBytesReceived = 0;

                while (true)
                {
                    bytes = new byte[bufferSize];
                    int bytesReceived = stream.Read(bytes, totalBytesReceived, bufferSize);
                    totalBytesReceived += bytesReceived;

                    string utfString = Encoding.UTF8.GetString(bytes, 0, bytesReceived);

                    if (string.IsNullOrEmpty(utfString))
                        break;

                    data += utfString;

                    if (bytesReceived < bufferSize)
                        break;
                }

                return Encrypt.DecryptString(data);
            }
            catch
            {
                return null;
            }
        }

谢谢。

var listener = new TcpListener(IPAddress.Loopback, ServerConfig.Port);

这是说 TcpListener 应该(仅)监听环回地址。这意味着服务器应该侦听仅来自本地机器的传入连接,而不是网络上的任何其他机器。

我想你想要 IPAddress.Any:

var listener = new TcpListener(IPAddress.Any, ServerConfig.Port);