简体   繁体   English

TCP连接C#中Socket的正确初始化和配置

[英]Correct initialization and configuration of Socket in TCP Connection C#

I have a question regarding the following code:我对以下代码有疑问:

    private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        private static readonly List<Socket> clientSockets = new List<Socket>();
        private const int BUFFER_SIZE = 1024*2;
        private static readonly byte[] buffer = new byte[BUFFER_SIZE];
        public static Manager Manager { get; set; }
        private static bool firstInit = true;

        /// <summary>
        /// Config and start the server
        /// </summary>
        public static void SetupServer()
        {
            try
            {
                Manager.PCForm.ConnectionButtonStatus(false);
                var PORT = int.Parse(Properties.Settings.Default.LocalPort);
                var listenToAny = Properties.Settings.Default.ListenToAny;
                var IP = GetSocketIP(listenToAny);

                Logger.LogInfo("Setting up server...");

                if(Properties.Settings.Default.UseLocalWifiNetwork)
                {
                    Logger.LogInfo("PC Local IP: " + LocalIPAddress);
                }
                else
                {
                    Logger.LogInfo("PC External IP: " + ExternalIPAddress);
                }           

                if(firstInit)
                {
                    firstInit = false;
                    Logger.LogDebug("Binding new port:" + PORT);
                    serverSocket.Bind(new IPEndPoint(IP, PORT));
                }
                else
                {
                    Logger.LogDebug("Using port that was already binded");
                }

                serverSocket.Listen(0);
                Logger.LogDebug("Listening To: " + IP + ":" + PORT);
                serverSocket.BeginAccept(AcceptCallback, null);
                Manager.PCForm.ConnectionButtonStatus(true);
                Logger.LogInfo("Server setup complete");
            }
            catch(Exception ex)
            {
                FormsHelpers.ShowErrorMessage(ex.Message);
                Logger.LogError("Fail to setup server. Please restart the app.");
            }
        }

   public static void CloseAllSockets()
        {
            try
            {
                Logger.LogDebug("Closing All Sockets...");
                Manager.PCForm.ConnectionButtonStatus(false);
                foreach(Socket socket in clientSockets.ToArray())
                {
                    CloseSocket(socket);
                }

                serverSocket.Close();
                Logger.LogInfo("Server was shutdown");
                Manager.PCForm.ConnectionButtonStatus(true);
            }
            catch(Exception ex)
            {
                Console.WriteLine("Fail to close sockets.\r\nExpection: " + ex.Message);
            }
        }

My problem started when I wanted to reuse a bound socket.当我想重用绑定的套接字时,我的问题就开始了。 My application supports closing and reopens TCP connection in the server (It can be the same port or a new one).我的应用程序支持关闭和重新打开服务器中的 TCP 连接(它可以是相同的端口或新端口)。

Scenario:设想:

1. The user starts the server (open a TCP socket in local IP and port 5000. 1. 用户启动服务器(在本地 IP 和端口 5000 中打开一个 TCP 套接字。

2. The user stops the server (The server closes the clients TCP connection and server socket) 2.用户停止服务器(服务器关闭客户端TCP连接和服务器socket)

3. The user starts the server again (same port - 5000 or new port if the user changed the port in app settings). 3. 用户再次启动服务器(相同的端口 - 5000 或新端口,如果用户在应用程序设置中更改了端口)。

When the user starts the server again with the same port (5000) I get the error: Cannot access a disposed object: When the user starts the server again with a new port (5001) I get the error.当用户使用相同的端口(5000)再次启动服务器时,我收到错误:无法访问已处置的 object:当用户使用新端口(5001)再次启动服务器时,我收到错误消息。 invalid argument (because the server socket was bound to a different port).无效参数(因为服务器套接字绑定到不同的端口)。

If I remove the code serverSocket.Close();如果我删除代码serverSocket.Close(); it will work because only without changing the port because of the fact that the server socket was never closed.它将起作用,因为仅由于服务器套接字从未关闭过而无需更改端口。 Look the netstat in that case:在这种情况下查看 netstat:

在此处输入图像描述

But this is not good because it doesn't allow to change the port unless the configuration is saved and the user restarts the application.但这并不好,因为除非保存配置并且用户重新启动应用程序,否则它不允许更改端口。

I updated the code.我更新了代码。 When I shut down the server I only disconnect the clients.当我关闭服务器时,我只断开客户端。 when I start the server I reuse the last socket but if I change the port I will close it and allocate a new instance of the socketServer and use it.当我启动服务器时,我重用了最后一个套接字,但如果我更改端口,我将关闭它并分配一个新的 socketServer 实例并使用它。

  if(portInUse.Equals(PORT))
                {
                    Logger.LogDebug("Using port that was already binded");
                }
                else
                {
                    Logger.LogDebug("Binding new port:" + PORT);

                    if(serverSocket != null)
                    {
                        //close previous socket because it was using old port
                        serverSocket.Close();
                    }

                    serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    serverSocket.Bind(new IPEndPoint(IP, PORT));
                    portInUse = PORT;
                }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM