客户端连续发送

下面修改一下上一节的服务器端,使得可以连续接收客户端发过来的消息,另外要开启多线程

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TcpServerDemo
{
    public partial class Form1 : Form
    {
        private TcpListener listener;
        private TcpClient tcpClient;

        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            Thread acceptThread = new Thread(() =>
            {
                IPAddress ip = IPAddress.Parse(this.textBoxIP.Text);//创建IP
                listener = new TcpListener(ip, Convert.ToInt32(this.textBoxPort.Text));//创建TCP监听对象
                listener.Start();
                this.textBoxInfo.Text = "服务器启动-" + DateTime.Now.ToShortTimeString() + "\r\n" + this.textBoxInfo.Text;
                tcpClient = listener.AcceptTcpClient();//中断 等待
                this.textBoxInfo.Text = "连接成功-" + DateTime.Now.ToShortTimeString() + "\r\n" + this.textBoxInfo.Text;

                NetworkStream stream = tcpClient.GetStream();
                byte[] byteArray = new byte[1024];
                while (true)
                {
                    int length = stream.Read(byteArray, 0, 1024);//会把流里面的字节数组 放到byteArray里面
                    //length其实就是客户端发送的字节数组长度
                    string receiveMessage = Encoding.Unicode.GetString(byteArray, 0, length);
                    this.textBoxInfo.Text = "接收到:" + receiveMessage + "-" +
                        DateTime.Now.ToShortTimeString() + "\r\n" + this.textBoxInfo.Text;
                }
            });
            acceptThread.IsBackground = true;
            acceptThread.Start();
        }
    }
}Code language: C# (cs)

基于 WinForms + TcpClient / TcpListener 实现:
客户端持续输入自定义文本发送给服务端,输入【退出】时断开连接、结束程序

代码演示用简单的方式解决多线程卡顿问题,但是更正确的应该是如下:
Control.CheckForIllegalCrossThreadCalls = false; 属于不推荐的暴力写法,正规方案使用 Invoke/BeginInvoke 跨线程更新控件。

一、服务端

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace TcpServerDemo
{
    public partial class Form1 : Form
    {
        private TcpListener listener;
        private TcpClient tcpClient;

        public Form1()
        {
            InitializeComponent();
            // 不推荐正式项目使用,仅学习演示
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            // 新开线程,防止UI阻塞
            new Thread(() =>
            {
                IPAddress ip = IPAddress.Parse(textBoxIP.Text);
                listener = new TcpListener(ip, Convert.ToInt32(textBoxPort.Text));
                listener.Start();
                AppendLog($"服务器启动-{DateTime.Now.ToShortTimeString()}");

                tcpClient = listener.AcceptTcpClient();
                AppendLog($"客户端连接成功-{DateTime.Now.ToShortTimeString()}");

                NetworkStream stream = tcpClient.GetStream();
                byte[] byteArray = new byte[1024];
                while (true)
                {
                    int length = stream.Read(byteArray, 0, 1024);
                    if (length <= 0)
                    {
                        AppendLog("客户端断开连接");
                        break;
                    }
                    string receiveMessage = Encoding.Unicode.GetString(byteArray, 0, length);
                    AppendLog($"接收到:{receiveMessage} -{DateTime.Now.ToShortTimeString()}");
                }
                tcpClient.Close();
                listener.Stop();
            }).Start();
        }

        // 追加日志到文本框
        private void AppendLog(string msg)
        {
            textBoxInfo.Text = msg + "\r\n" + textBoxInfo.Text;
        }
    }
}Code language: C# (cs)

二、客户端代码

实现【连续输入,输入“退出”结束】

客户端界面建议准备:

  • textBoxServerIp:服务端IP
  • textBoxPort:端口
  • textBoxSend:输入待发送消息
  • btnConnect:连接按钮
  • btnSend:发送按钮
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TcpClientDemo
{
    public partial class ClientForm : Form
    {
        private TcpClient client;
        private NetworkStream stream;
        private bool isConnected = false;

        public ClientForm()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        // 连接服务器
        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                client = new TcpClient();
                client.Connect(textBoxServerIp.Text, Convert.ToInt32(textBoxPort.Text));
                stream = client.GetStream();
                isConnected = true;
                MessageBox.Show("连接成功,可以开始发送消息!");
            }
            catch (Exception ex)
            {
                MessageBox.Show("连接失败:" + ex.Message);
            }
        }

        // 发送消息核心逻辑
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (!isConnected)
            {
                MessageBox.Show("请先连接服务器!");
                return;
            }
            string content = textBoxSend.Text.Trim();
            if (string.IsNullOrEmpty(content))
                return;

            // 判断是否输入退出指令
            if (content == "退出")
            {
                byte[] exitData = Encoding.Unicode.GetBytes(content);
                stream.Write(exitData, 0, exitData.Length);

                // 关闭资源
                stream.Close();
                client.Close();
                isConnected = false;
                MessageBox.Show("已断开连接");
                return;
            }

            // 正常发送自定义内容
            byte[] data = Encoding.Unicode.GetBytes(content);
            stream.Write(data, 0, data.Length);
            textBoxSend.Clear();
        }
    }
}Code language: C# (cs)
static void Main(string[] args)
{
    TcpClient client = new TcpClient();
    client.Connect("127.0.0.1", 8899);
    NetworkStream stream = client.GetStream();
    while (true)
    {
        Console.Write("请输入发送内容:");
        string msg = Console.ReadLine();
        byte[] buf = Encoding.Unicode.GetBytes(msg);
        stream.Write(buf,0,buf.Length);
        if (msg == "退出")
        {
            stream.Close();
            client.Close();
            break;
        }
    }
}Code language: JavaScript (javascript)

如果你需要,我可以把整套代码改成纯异步async/await写法,彻底抛弃子线程+禁用跨线程检查这种不规范方式。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注