C#TCPListener仅在应用程序关闭后才保持第一次监听

时间:2018-07-25 09:15:13

标签: c# networking tcp port tcplistener

我的申请有问题, 我有一个TCPListener,让我们在端口14000上监听 关闭应用程序后,我可以在CMD上看到侦听器仍在侦听。 在应用程序的第二次运行中,按预期的那样,我无法在同一端口(14000)上启动侦听器,因为在第二次运行时,我将应用程序端口更改为15000,工作非常好,并且侦听器在关闭后已关闭应用程序正在关闭, 我假设第一次运行时,应用程序死后,端口14000上的第一个侦听器保持打开状态,而第二次运行时,应用程序关闭/很好地打开了端口15000上的侦听器,为什么会发生这种情况?我以为可能是关于端口14000的问题我已经切换了打开端口的顺序(首先打开了15000),发现15000保持打开状态,而14000(第二次运行)已正确关闭并打开,为什么在第一次运行听众没有被关闭? 我服务器的代码:

class Server : IDisposable
{
    private const int TIMER_PERIOD = 60 * 1000; // ms
    private string servePort;
    private string serverIP;
    byte[] DataReceived = new byte[1024];
    Action<string> MssageReceiveCallback;
    private bool isListening = false;
    static Timer serverTimer = null;
    private TcpListener _Server;
    private Dictionary<int, TcpClient> clientsList = new Dictionary<int, TcpClient>();
    private bool serverListening = true;
    private static int ClientInstance = 0;


    public Server(string _serverIP, string _serverPORT, Action<string> messageReceiveCallback)
    {
        serverIP = _serverIP;
        servePort = _serverPORT;
        MssageReceiveCallback = messageReceiveCallback;
        // InitilizeServer();
    }

    private void InitilizeServer()
    {

        _Server = new TcpListener(IPAddress.Parse(serverIP), int.Parse(servePort));

        // if (serverTimer == null)
        //     serverTimer = new Timer(new TimerCallback(OnTimerCallback), null, TIMER_PERIOD, TIMER_PERIOD);

        Task.Run(() =>
        {
            try
            {
                _Server.Start();

                while (_Server != null)
                {
                    TcpClient tcpClient;
                    try
                    {
                        tcpClient = _Server.AcceptTcpClient();
                    }
                    catch
                    {
                        continue;
                    }

                    Task.Run(() =>
                    {
                        ClientInstance++;
                        int currentinstance = ClientInstance;
                        clientsList.Add(currentinstance, tcpClient);
                        try
                        {
                            while (tcpClient.Connected && serverListening)
                            {
                                if (tcpClient.GetStream().DataAvailable)
                                {
                                    int actualBufferlength = tcpClient.GetStream().Read(DataReceived, 0, DataReceived.Length);
                                    byte[] data = new byte[actualBufferlength];
                                    Buffer.BlockCopy(DataReceived, 0, data, 0, actualBufferlength);

                                    string asciiMessage = Encoding.ASCII.GetString(data);
                                    MssageReceiveCallback(asciiMessage);
                                }
                                else
                                {
                                    Thread.Sleep(5);
                                }
                            }

                        }
                        catch (Exception ex)
                        {
                        }
                        finally
                        {
                            clientsList[currentinstance].Close();
                            clientsList.Remove(currentinstance);
                        }
                    });
                }
            }
            catch (Exception ex)
            {
            }
        });
    }



    public void StartServer()
    {
        InitilizeServer();
        isListening = true;
    }

    public void SendMessage(string msg)
    {
        byte[] data = ASCIIEncoding.ASCII.GetBytes(msg);
        foreach (TcpClient client in clientsList.Values)
        {
            client.GetStream().Write(data, 0, data.Length);
        }
    }

    public void Dispose()
    {
        serverListening = false;
        foreach (var item in clientsList.Values)
        {
            if (item.Connected)
                item.Close();
        }
        _Server.Server.Close();
    }
}

更新: 我已经在TCPView中签入,以查看侦听器绑定到哪个应用程序并发现了以下内容: enter image description here

似乎监听器可用于不存在的进程

2 个答案:

答案 0 :(得分:1)

我认为这里最大的问题(我已经在注释中指出了其他问题)是TCP关闭需要网络通信,并且默认情况下会在一段时间内阻止套接字重用。 >

您需要使用的功能是Socket.SetSocketOption,特别是ReuseAddress选项。您应该能够通过Server上的TcpListener属性来进行操作。请注意,必须在实际开始侦听器之前 完成。

答案 1 :(得分:0)

您可以尝试放置:

_Server.Server =null;

关闭后。