关闭并重新打开客户端表单后,C#TCP客户端重新连接

时间:2018-11-28 13:40:01

标签: c# winforms tcp chat

我用C#WinForms编写了一个聊天应用程序。但是,如果我关闭客户端表单(此表单连接到服务器表单时)并重新打开客户端表单并尝试重新连接,则客户端不会连接到服务器。

如果关闭并重新打开应用程序,如何将客户端重新连接到服务器?

(对不起,英语不好)

服务器:

    public frmServer()
    {
        InitializeComponent();
        textBox_Hostname.Text = GetLocalIPAddress();
        Configuration Programmkonfiguration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        Port = Programmkonfiguration.AppSettings.Settings["Port"].Value;
        textBox_Port.Text = Port;
        toolStripStatusLabel_Serverstatus.Text = "deaktiviert";
        toolStripStatusLabel_Serverstatus.ForeColor = Color.Red;
        textBox_Output.Focus();
    }

    private string GetLocalIPAddress()
    {
        var host = Dns.GetHostEntry(Dns.GetHostName());
        foreach (var ip in host.AddressList)
        {
            if (ip.AddressFamily == AddressFamily.InterNetwork)
            {
                return ip.ToString();
            }
        }
        throw new Exception("No network adapters with an IPv4 address in the system!");
    }

    private void button_Send_Click(object sender, EventArgs e)
    {
        if (!(string.IsNullOrWhiteSpace(textBox_Output.Text)))
        {
            String s = "Server: " + textBox_Output.Text + Environment.NewLine;
            textBox_Input.Text += s;
            byte[] byteTime = Encoding.ASCII.GetBytes(s);
            ns.Write(byteTime, 0, byteTime.Length);
            textBox_Output.Clear();
        }
    }

    public void DoWork()
    {
        byte[] bytes = new byte[1024];
        while (true)
        {
            int bytesRead = ns.Read(bytes, 0, bytes.Length);
            this.SetText(Encoding.ASCII.GetString(bytes, 0, bytesRead));
        }
    }

    private void SetText(string text)
    {
        if (this.textBox_Input.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.textBox_Input.Text = this.textBox_Input.Text + text;
        }
    }

    private void button_Starten_Click(object sender, EventArgs e)
    {
        IPAddress hostname = IPAddress.Parse(textBox_Hostname.Text);
        int portNum = Convert.ToInt32(textBox_Port.Text);
        listener = new TcpListener(hostname, portNum);
        listener.Start();
        Task TCPListener = new Task(() => AcceptTCP());
        TCPListener.Start();
        textBox_Input.Text += "Server gestartet." + Environment.NewLine;
        button_Starten.Enabled = false;
        toolStripStatusLabel_Serverstatus.Text = "aktiviert";
        toolStripStatusLabel_Serverstatus.ForeColor = Color.Green;
    }

    private void AcceptTCP()
    {
        client = listener.AcceptTcpClient();
        ns = client.GetStream();
        Task Work = new Task(() => DoWork());
        Work.Start();
    }

    private void textBox_Output_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            button_Send_Click(sender, e);
            e.Handled = true;
            textBox_Output.Focus();
        }
    }
}

客户:

    public frmClient()
    {
        InitializeComponent();
        Configuration Programmkonfiguration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        HostnameServer = Programmkonfiguration.AppSettings.Settings["HostnameServer"].Value;
        Port = Programmkonfiguration.AppSettings.Settings["Port"].Value;
        textBox_Hostname.Text = GetLocalIPAddress();
        textBox_Port.Text = Port;
        toolStripStatusLabel_Status.Text = " nicht verbunden";
        toolStripStatusLabel_Status.ForeColor = Color.Red;
        textBox_Output.Focus();
    }

    private string GetLocalIPAddress()
    {
        var host = Dns.GetHostEntry(HostnameServer);
        foreach (var ip in host.AddressList)
        {
            if (ip.AddressFamily == AddressFamily.InterNetwork)
            {
                return ip.ToString();
            }
        }
        throw new Exception("No network adapters with an IPv4 address in the system!");
    }


    private void button_Senden_Click(object sender, EventArgs e)
    {
        if (!(string.IsNullOrWhiteSpace(textBox_Output.Text)))
        {
            String s = "Client: " + textBox_Output.Text + Environment.NewLine;
            textBox_Input.Text += s;
            byte[] byteTime = Encoding.ASCII.GetBytes(s);
            ns.Write(byteTime, 0, byteTime.Length);
            textBox_Output.Clear();
        }
    }

    public void DoWork()
    {
        byte[] bytes = new byte[1024];
        while (true)
        {
            if (ns.DataAvailable)
            {
                int bytesRead = ns.Read(bytes, 0, bytes.Length);
                this.SetText(Encoding.ASCII.GetString(bytes, 0, bytesRead));
            }
        }
    }

    private void SetText(string text)
    {
        if (this.textBox_Input.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.textBox_Input.Text = this.textBox_Input.Text + text;
        }
    }

    private void button_Connect_Click(object sender, EventArgs e)
    {
        string hostName = textBox_Hostname.Text;
        int portNum = Convert.ToInt32(textBox_Port.Text);
        client = new TcpClient(hostName, portNum);
        ns = client.GetStream();
        Work = new Task(() => DoWork());
        Work.Start();
        textBox_Input.Text += "Verbindung hergestellt." + Environment.NewLine;
        button_Connect.Enabled = false;
        toolStripStatusLabel_Status.Text = "verbunden";
        toolStripStatusLabel_Status.ForeColor = Color.Green;
    }

    private void textBox_Output_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            button_Senden_Click(sender, e);
            e.Handled = true;
            textBox_Output.Focus();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

在侦听器套接字上对Accept的每次调用都接受一个连接。目前,您的服务器接受单个连接请求,然后从该点开始忽略监听器套接字。

通常,您需要某种形式的“ Accept循环”来连续调用Accept,为该连接设置服务器端资源,然后循环返回以再次调用Accept

例如简单的更改是这样做:

private void AcceptTCP()
{
    while(true)
    {
      client = listener.AcceptTcpClient();
      ns = client.GetStream();
      Task Work = new Task(() => DoWork());
      Work.Start();
    }
}

但是现在您真的必须考虑ns会发生什么-如果/当您希望同时连接第二个客户端时会发生什么?将NetworkStream设为服务器内的单个共享实例变量并不能很好地扩展。

通常,您需要创建某种形式的简单类,以表示每个连接以及与该连接有关的服务器特定信息。例如。它会包含NetworkStream,此连接的当前“状态”(如果您有模式或状态),也可能是在您开始进行{{时,最后一次传递给Read调用的缓冲区1}},等等。