C#基于Sockets类实现TCP通讯的具体代码

Ada
Ada
发布时间:2026-10-13 | 2人浏览过
原创

本文详细介绍如何使用C#中的System.Net.Sockets.Socket类实现TCP通讯。包含完整的客户端连接与接收逻辑,以及服务端的监听、接受连接和消息收发功能。通过Windows Forms界面示例,展示IP地址、端口配置及多线程处理机制,提供可直接运行的核心代码片段。

TCP通讯原理与目标

TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在C#开发中,Socket 类提供了对底层网络通信的控制能力。本文将演示如何构建一个简单的 TCP 客户端(Client)和服务端(Server),实现双方数据的相互发送与接收。

最终实现的界面效果如下:

第一部分:TCP客户端实现

第1步:创建客户端窗体并初始化控件

客户端需要输入服务端的 IP 地址和端口号来发起连接,同时提供发送消息的输入框和显示日志的文本框。界面结构如上图所示。

第2步:建立 Socket 连接

点击“连接”按钮时,执行以下操作:

  • 实例化 Socket 对象,指定地址族为 AddressFamily.InterNetwork(IPv4),套接字类型为 SocketType.Stream(流式),协议类型为 ProtocolType.Tcp。
  • 解析输入的 IP 字符串并转换为 IPAddress 对象。
  • 组合 IPEndPoint,包含 IP 和端口号。
  • 调用 Connect 方法发起连接。
  • 启动一个后台线程专门用于接收服务器发来的消息。
using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;

namespace TCPClient02
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        
        // 用于发送数据的Socket实例
        Socket socketSend;
        
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                // 1. Create socket
                socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                
                // 2. 获取IP和端口
                IPAddress ip = IPAddress.Parse(textBox1.Text);
                IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(textBox2.Text));
                
                // 3. 建立连接
                socketSend.Connect(point);
                ShowMessages("Connection succeeded");

                // 4. 启动接收线程
                Thread th = new Thread(ReciveMessages);
                th.IsBackground = true;
                th.Start();
            }
            catch (Exception ex)
            {
                ShowMessages("连接失败: " + ex.Message);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            string str = textBox3.Text.Trim();
            if (!string.IsNullOrEmpty(str) && socketSend != null)
            {
                // 将字符串转换为UTF-8字节数组并发送
                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
                socketSend.Send(buffer);
                // 清空输入框以便下次输入
                textBox3.Text = "";
            }
        }

        void ShowMessages(string str)
        {
            textBox4.AppendText(str + "\r\n");
        }
        
        // 持续接收服务器消息的方法
        void ReciveMessages()
        {
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024 * 1024 * 3]; // 缓冲区大小3MB
                    int r = socketSend.Receive(buffer);
                    
                    // 如果收到0字节,说明连接已关闭
                    if (r == 0)
                    {
                        break;
                    }
                    
                    string s = Encoding.UTF8.GetString(buffer, 0, r);
                    ShowMessages(socketSend.RemoteEndPoint + ":" + s);
                }
                catch
                {
                    break;
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 禁用跨线程检查,允许在非UI线程更新控件
            Control.CheckForIllegalCrossThreadCalls = false;
        }
    }
}

客户端界面示意:

第二部分:TCP服务端实现

第3步:设置服务端监听

服务端启动后,需创建一个负责监听的 Socket,绑定到本地 IP 和端口,并开始监听 incoming 连接请求。

  • IP 通常设置为 IPAddress.Any 以监听所有网卡接口。
  • 调用 Bind 绑定端点。
  • 调用 Listen 设置等待队列长度( backlog )。
  • 启动一个主线程调用 Accept 阻塞等待客户端连接。

第4步:处理客户端连接与数据收发

当 Accept 成功返回一个新的 Socket 后,该 Socket 专用于与该客户端通信。此时应启动一个新的后台线程来处理该客户端的消息接收,从而支持多客户端并发(尽管本示例仅展示单连接处理的逻辑基础)。

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

namespace TCPserver
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                // 1. 创建一个负责监听的Socket
                Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                
                // 2. 绑定IP和端口
                IPAddress ip = IPAddress.Any; // 监听所有IP
                IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(textBox2.Text));
                socketWatch.Bind(point);

                ShowMsg("监听成功");
                
                // 3. 开始监听,队列长度10
                socketWatch.Listen(10);

                // 4. 启动监听线程
                Thread th = new Thread(Listen);
                th.IsBackground = true;
                th.Start(socketWatch);
            }
            catch (Exception ex)
            {
                ShowMsg("启动失败: " + ex.Message);
            }
        }

        void ShowMsg(string str)
        {
            textBox3.AppendText(str + "\r\n");
        }

        // 当前已接受的用于通信的Socket
        Socket socketSend;
        
        /// <summary>
        /// 等待客户端的连接 并且创建与之通信的Socket
        /// </summary>
        void Listen(object o)
        {
            Socket socketWatch = o as Socket;
            while (true)
            {
                try
                {
                    // 阻塞直到有客户端连接
                    socketSend = socketWatch.Accept();
                    ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功");
                    
                    // 为每个新连接启动接收线程
                    Thread th = new Thread(Recive);
                    th.IsBackground = true;
                    th.Start(socketSend);
                }
                catch
                {
                    break;
                }
            }
        }
        
        /// <summary>
        /// 服务器不断接受客户端发送过来的消息
        /// </summary>
        void Recive(object o)
        {
            Socket socketSend = o as Socket;
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024 * 1024 * 2]; // 缓冲区2MB
                    // 实际接收到的有效字节数
                    int bytelen = socketSend.Receive(buffer);
                    
                    if (bytelen == 0)
                    {
                        break; // 客户端断开
                    }
                    
                    string str = Encoding.UTF8.GetString(buffer, 0, bytelen);
                    ShowMsg(socketSend.RemoteEndPoint + ":" + str);
                }
                catch
                {
                    break;
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }

       /// <summary>
       /// 服务器给客户端发送消息
       /// </summary>
        private void button3_Click(object sender, EventArgs e)
        {
            string str = textBox4.Text;
            if (!string.IsNullOrEmpty(str) && socketSend != null)
            {
                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
                socketSend.Send(buffer);
            }
        }
    }
}

服务端界面示意:

关键注意事项

  • 跨线程访问:由于接收消息是在后台线程中进行的,而更新 UI(文本框)必须在主线程(UI线程)进行。示例代码中使用 Control.CheckForIllegalCrossThreadCalls = false; 禁用了检查以简化操作,但在生产环境中建议使用 Invoke 或 BeginInvoke 安全地更新 UI。
  • 编码格式:代码中统一使用 UTF-8 进行字节编码和解码,确保中文等字符正确传输。
  • 异常处理:实际应用中应对 Send、Receive 和网络断开情况做更细致的异常捕获和资源释放(关闭 Socket)。
  • 端口占用:如果启动服务端时报错,请确认所选端口未被其他程序占用。
以上就是基于C# Sockets类实现TCP通讯的详细内容,更多关于C# Socket网络编程的资料请关注本站其它相关文章!
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表