TcpClient TcpListener

服务器

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ChatDemo01
{
    public partial class MainFrm : Form
    {
        // 定义网络组件
        private TcpListener listener;
        private TcpClient client;
        private NetworkStream stream;

        public MainFrm()
        {
            InitializeComponent();
        }

        // “开始”按钮点击事件,用于启动服务器并监听客户端连接
        private void btnStart_Click(object sender, EventArgs e)
        {
            ConnectToClient(txtIP.Text, int.Parse(txtPort.Text));
        }

        #region 启动服务器并监听客户端连接的方法
        // 启动服务器并监听客户端连接的方法
        private void ConnectToClient(string ipAddress, int port)
        {
            try
            {
                listener = new TcpListener(IPAddress.Parse(ipAddress), port);
                listener.Start();
                AppendTextToTxtLog("服务器正在监听...");

                // 使用线程池接受客户端连接,避免阻塞UI线程
                ThreadPool.QueueUserWorkItem(AcceptClientConnect, listener);
            }
            catch (Exception ex)
            {
                AppendTextToTxtLog($"连接失败: {ex.Message}");
            }
        }
        #endregion

        #region 接受客户端连接的回调方法
        // 接受客户端连接的回调方法
        private void AcceptClientConnect(object state)
        {
            listener = (TcpListener)state;
            client = listener.AcceptTcpClient();
            AppendTextToTxtLog("客户端已连接");

            stream = client.GetStream(); // 获取网络流以便读写操作
            ThreadPool.QueueUserWorkItem(ReceiveData, client); // 开始接收客户端消息
        }
        #endregion

        #region 发送消息到客户端
        // 发送消息到客户端
        private void SendMessage(string message)
        {
            if (client != null && client.Connected)
            {
                try
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(message); // 编码消息为字节流
                    stream.Write(bytes, 0, bytes.Length);
                    AppendTextToTxtLog("消息已发送。");
                }
                catch (Exception ex)
                {
                    AppendTextToTxtLog($"发送消息时出错: {ex.Message}");
                }
            }
            else
            {
                AppendTextToTxtLog("未连接到客户端。");
            }
        }
        #endregion

        #region 接收客户端消息的方法
        // 接收客户端消息的方法
        private void ReceiveData(object state)
        {
            client = (TcpClient)state;
            byte[] data = new byte[1024 * 1024]; // 缓冲区大小
            while (true)
            {
                try
                {
                    int len = stream.Read(data, 0, data.Length);
                    if (len > 0)
                    {
                        string message = Encoding.UTF8.GetString(data, 0, len);
                        AppendTextToTxtLog($"收到消息: {message}");

                        // 简单回显消息给客户端
                        byte[] response = Encoding.UTF8.GetBytes(message);
                        stream.Write(response, 0, response.Length);
                        stream.Flush();
                    }
                }
                catch (Exception ex)
                {
                    AppendTextToTxtLog($"接收数据时出错: {ex.Message}");
                    break; // 发生异常时退出循环
                }
            }
        }
        #endregion

        #region 往日志文本框追加显示信息的方法
        // 往日志文本框追加显示信息的方法,考虑了线程安全
        public void AppendTextToTxtLog(string txt)
        {
            if (txtLog.InvokeRequired)
            {
                txtLog.Invoke((MethodInvoker)(() => txtLog.Text += $"{txt}\r\n"));
            }
            else
            {
                txtLog.Text += $"{txt}\r\n";
            }
        }
        #endregion

        #region 发送按钮点击事件
        // 发送按钮点击事件
        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            SendMessage(txtMsg.Text);
        }

        // 关闭窗口前确保关闭客户端连接
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            if (client != null && client.Connected)
            {
                client.Close();
                AppendTextToTxtLog("服务器已关闭。");
            }
        }
        #endregion
    }
}

客户端

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

namespace SocketClient01
{
    public partial class MainFrm : Form
    {
        private TcpClient client;
        private NetworkStream stream;

        // 构造函数初始化
        public MainFrm()
        {
            InitializeComponent();
        }

        // 连接按钮点击事件,尝试连接服务器
        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                client = new TcpClient();
                client.Connect(txtIP.Text, int.Parse(txtPort.Text)); // 使用IP地址和端口连接服务器
                AppendTextToTxtLog("已成功连接到服务器");

                stream = client.GetStream(); // 初始化网络流

                // 创建并启动后台线程用于接收服务器数据
                Thread receiveThread = new Thread(ReceiveData);
                receiveThread.IsBackground = true; // 设置为后台线程,程序退出时自动关闭
                receiveThread.Start(client); // 传递客户端实例给线程
            }
            catch (SocketException se)
            {
                AppendTextToTxtLog($"连接服务器失败: {se.Message}");
            }
            catch (FormatException fe)
            {
                AppendTextToTxtLog($"端口号格式错误: {fe.Message}");
            }
        }
        #region 接收服务器数据的方法
        // 接收服务器数据的方法
        private void ReceiveData(object state)
        {
            TcpClient client = (TcpClient)state;
            NetworkStream stream = client.GetStream();

            byte[] buffer = new byte[1024];
            while (client.Connected)
            {
                try
                {
                    int received = stream.Read(buffer, 0, buffer.Length);
                    if (received > 0)
                    {
                        string message = Encoding.UTF8.GetString(buffer, 0, received);
                        AppendTextToTxtLog($"接收到服务器消息: {message}");
                    }
                }
                catch (IOException) // 当连接断开时会抛出此异常
                {
                    AppendTextToTxtLog("与服务器的连接已断开。");
                    break;
                }
            }
            client.Close(); // 断开连接后关闭客户端
        }
        #endregion

        #region 往日志文本框追加显示信息的方法
        // 往日志文本框追加显示信息的方法,考虑了线程安全
        public void AppendTextToTxtLog(string txt)
        {
            if (txtLog.InvokeRequired)
            {
                txtLog.Invoke((MethodInvoker)(() => txtLog.Text += $"{txt}\r\n"));
            }
            else
            {
                txtLog.Text += $"{txt}\r\n";
            }
        }
        #endregion

        #region 发送消息按钮点击事件
        // 发送消息按钮点击事件
        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            if (client == null || !client.Connected)
            {
                AppendTextToTxtLog("未连接到服务器。");
                return;
            }

            try
            {
                string message = txtMsg.Text.Trim();
                byte[] data = Encoding.UTF8.GetBytes(message);
                stream.Write(data, 0, data.Length);
                stream.Flush();
                AppendTextToTxtLog("消息已发送。");
                txtMsg.Clear(); // 发送后清空输入框
            }
            catch (Exception ex)
            {
                AppendTextToTxtLog($"发送消息时出错: {ex.Message}");
            }
        }
        #endregion
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值