为什么服务器没有关闭?

时间:2019-07-10 15:13:30

标签: c# tcp client-server

以下源代码轮询传入的客户端连接。

class ServerForm : Form
{
    //...

    void PollIncomingClientConns(TcpListener listener)
    {
        listener.Start();

        _keepPolling = true;

        try
        {
            while (_keepPolling)
            {
                ClientClass client = new ClientClass(listener);
                ClientDictionary.Add(client.ID, client);

                SetStringToTextBox("Client [" + client.ID + "] is now connected.");

                Thread thread = new Thread(delegate()
                {
                    ReadFromClient(client);
                });
                thread.IsBackground = true;
                thread.Start();
            }

            _tcplistener.Server.Close();
            _tcplistener.Server.Dispose();
            _tcplistener = null;
        }
        catch (Exception ex)
        {
            var inner = ex.InnerException as SocketException;

            if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
            {
                SetStringToTextBox("Disconnected");
            }
            else
            {
                SetStringToTextBox(ex.Message);
            }

            listener.Stop();
        }
    }

    void ReadFromClient(ClientClass client)
    {
        try
        {
            while (true)
            {
                string str = client.Read();
                SetStringToTextBox("[" + client.ID + "] says: " + str);

                switch (str)
                {
                    // ... service client requests ...
                    // ... text messages ...
                }

                if (!client.Tcp.Connected) 
                {  
                    SetStringToTextBox("[" + client.ID + "] is disconnected.");
                    client.Close();
                    break;
                }
            }
        }
        catch
        {
            client.Close();
        }
    } 
    // ...
}

为了关闭服务器,我单击了一个按钮,并将_keepPolling设置为false。

但是,在客户端,我发现客户端仍然能够连接到服务器。即服务器没有关闭。

如何解决此问题?


相关源代码

以下是客户端源代码,

public class ClientClass
{
    public string ID { get; private set; }
    public string Host { get; set; }
    public int Port { get; set; }        

    public TcpClient Tcp { get; private set; }
    private BinaryReader reader;
    private BinaryWriter writer;

    /// <summary>
    /// Creates a clienbt at the Client-end. 
    /// This requires Host and Post property to be set.
    /// </summary>
    public ClientClass()
    {
        Random rnd = new Random();
        ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
    }

    /// <summary>
    /// Creates a client at the Client-end.
    /// </summary>
    /// <param name="host"></param>
    /// <param name="port"></param>
    public ClientClass(string host, int port)
    {
        Random rnd = new Random();
        ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
        Host = host;
        Port = port;
    }

    /// <summary>
    /// creates a proxy-client at the Server-end.
    /// </summary>
    /// <param name="listener"></param>
    public ClientClass(TcpListener listener)
    {
        Tcp  = listener.AcceptTcpClient();

        Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
        Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;

        NetworkStream stream = Tcp.GetStream();
        reader = new BinaryReader(stream);
        writer = new BinaryWriter(stream);

        ID = Read();
    }

    /// <summary>
    /// Connects the client to the server.
    /// </summary>
    /// <returns></returns>
    public bool Connect()
    {
        bool is_connected = IsConnected();

        if (!is_connected)
        {
            Tcp = new TcpClient(Host, Port);

            NetworkStream stream = Tcp.GetStream();
            reader = new BinaryReader(stream);
            writer = new BinaryWriter(stream);

            return true;
        }
        else if (is_connected)
        {
            return true;
        }
        else return false;
    }

    public bool IsConnected()
    {
        if (Tcp == null)
        {
            return false;
        }
        else
        {
            Socket s = Tcp.Client;

            bool part1 = s.Poll(1000, SelectMode.SelectRead);
            bool part2 = (s.Available == 0);
            if ((part1 && part2) || !s.Connected)
                return false;
            else
                return true;
        }
    }

    public void Write(string str)
    {
        if (IsConnected())
        {
            byte[] strBytes = Encoding.UTF8.GetBytes(str);
            byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
            Array.Reverse(lenBytes);
            writer.Write(lenBytes);
            writer.Write(strBytes);
            writer.Flush();
        }
        else
        {
            throw new Exception("Client " + ID + " is not connected!");
        }
    }

    public string Read()
    {
        if (IsConnected())
        {
            byte[] lenBytes = reader.ReadBytes(4);
            Array.Reverse(lenBytes);
            int len = BitConverter.ToInt32(lenBytes, 0);
            byte[] bytes = reader.ReadBytes(len);
            string str = Encoding.UTF8.GetString(bytes);

            return str;
        }
        else
        {
            throw new Exception("Client " + ID + " is not connected!");
        }
    }

    public void PrintID()
    {
        Console.WriteLine("Client ID = {0}", ID);
    }

    public void SendIdToServer()
    {
        this.Write(ID);
    }

    public bool Close()
    {
        if (IsConnected())
        {
            if (Tcp != null)
            {                
                Tcp.Close();
                Tcp = null;

                return true;
            }
        }

        return false;
    }
}

编辑:

class ServerForm : Form
{
    // ...
    private void startToolStripMenuItem_Click(object sender, EventArgs e)
    {
        string ipAddress = Constants.LOCAL_HOST_IP;
        int portNo = Constants.PORT_NO;

        IPAddress ip = IPAddress.Parse(ipAddress);
        _tcplistener = new TcpListener(ip, portNo);

        // poll for clients in a 2nd thread
        Thread thread = new Thread(delegate()
        {
            PollIncomingClientConns(_tcplistener);
        });
        thread.IsBackground = true;
        thread.Start();

        SetStringToTextBox("Server program started on address [" + ipAddress + ":" + portNo + "]");

        startToolStripMenuItem.Enabled = false;
        stopToolStripMenuItem.Enabled = true;
    }
    // ...
}

1 个答案:

答案 0 :(得分:0)

经过一些测试,只需调用_tcplistener.Stop();就可以了。在将_keepPolling设置为false的地方调用它