C#如何搭建TCP/IP服务端和客户端实现Socket通信

来源:站长工具作者:松松建站头衔:草根站长
导读:本期聚焦于小伙伴创作的《C#如何搭建TCP/IP服务端和客户端实现Socket通信》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#如何搭建TCP/IP服务端和客户端实现Socket通信》有用,将其分享出去将是对创作者最好的鼓励。

在C#开发中,基于TCP/IP协议的Socket通信是实现跨进程、跨设备可靠数据传输的核心技术,相比UDP协议,它具备连接稳定、数据无丢失、传输顺序有保障的特点,广泛应用于即时通讯、物联网数据上报、分布式系统交互等场景。

C#如何搭建TCP/IP服务端和客户端实现Socket通信

Socket通信核心原理

TCP/IP协议下的Socket通信遵循三次握手建立连接、四次挥手断开连接的流程,通信双方分为服务端和客户端两个角色:

  • 服务端需要先绑定指定端口,监听端口上的连接请求,接收客户端连接后与客户端建立独立的通信通道
  • 客户端需要主动发起连接请求,指定服务端的IP地址和端口,连接建立后即可双向传输数据
  • 每个成功的连接都会在服务端生成一个对应的Socket对象,用于和该客户端进行专属通信

TCP服务端搭建实现

基础服务端代码示例

以下代码实现了支持多客户端连接的异步TCP服务端,避免了同步阻塞导致的性能问题:

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

namespace SocketServerDemo
{
    class TcpServer
    {
        // 服务端监听的端口
        private static int port = 8888;
        // 用于统计客户端连接数
        private static int clientCount = 0;

        static void Main(string[] args)
        {
            // 创建Socket对象,使用IPv4、流类型、TCP协议
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            // 绑定IP和端口,IPAddress.Any表示监听所有本机网卡
            serverSocket.Bind(new IPEndPoint(IPAddress.Any, port));
            // 开始监听,参数表示等待连接的最大队列长度
            serverSocket.Listen(10);
            Console.WriteLine($"服务端已启动,监听端口:{port},等待客户端连接...");

            // 异步接收客户端连接
            serverSocket.BeginAccept(AcceptCallback, serverSocket);

            // 保持主线程运行,避免程序退出
            Console.ReadLine();
        }

        // 接收客户端连接的回调函数
        static void AcceptCallback(IAsyncResult ar)
        {
            Socket serverSocket = (Socket)ar.AsyncState;
            try
            {
                // 完成连接接收,返回和客户端的通信Socket
                Socket clientSocket = serverSocket.EndAccept(ar);
                clientCount++;
                Console.WriteLine($"客户端已连接,当前连接数:{clientCount},客户端地址:{clientSocket.RemoteEndPoint}");

                // 给客户端发送欢迎消息
                string welcomeMsg = "欢迎连接TCP服务端";
                byte[] sendData = Encoding.UTF8.GetBytes(welcomeMsg);
                clientSocket.Send(sendData);

                // 开启异步接收客户端数据
                byte[] buffer = new byte[1024];
                clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, new object[] { clientSocket, buffer });

                // 继续接收下一个客户端连接
                serverSocket.BeginAccept(AcceptCallback, serverSocket);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接收客户端连接异常:{ex.Message}");
            }
        }

        // 接收客户端数据的回调函数
        static void ReceiveCallback(IAsyncResult ar)
        {
            object[] objs = (object[])ar.AsyncState;
            Socket clientSocket = (Socket)objs[0];
            byte[] buffer = (byte[])objs[1];
            try
            {
                // 完成数据接收,返回接收的字节数
                int receiveLength = clientSocket.EndReceive(ar);
                if (receiveLength > 0)
                {
                    string receiveMsg = Encoding.UTF8.GetString(buffer, 0, receiveLength);
                    Console.WriteLine($"收到客户端{clientSocket.RemoteEndPoint}消息:{receiveMsg}");

                    // 回传数据给客户端
                    string responseMsg = $"服务端已收到你的消息:{receiveMsg}";
                    byte[] responseData = Encoding.UTF8.GetBytes(responseMsg);
                    clientSocket.Send(responseData);

                    // 继续接收下一段数据
                    clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, new object[] { clientSocket, buffer });
                }
                else
                {
                    // 接收长度为0说明客户端已断开连接
                    clientSocket.Close();
                    clientCount--;
                    Console.WriteLine($"客户端已断开连接,当前连接数:{clientCount}");
                }
            }
            catch (SocketException)
            {
                // 客户端异常断开连接
                clientSocket.Close();
                clientCount--;
                Console.WriteLine($"客户端异常断开,当前连接数:{clientCount}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接收数据异常:{ex.Message}");
            }
        }
    }
}

服务端进阶优化点

  • 使用BeginAcceptBeginReceive异步方法替代同步阻塞方法,避免单客户端阻塞导致其他客户端无法连接
  • 添加心跳检测机制,定时向客户端发送心跳包,若多次未收到客户端响应则主动断开连接,清理无效连接
  • 处理数据粘包问题:可以在数据开头添加长度字段,接收时先读取长度信息,再拼接完整数据包

TCP客户端搭建实现

基础客户端代码示例

以下代码实现了可主动连接服务端、发送消息并接收响应的TCP客户端:

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

namespace SocketClientDemo
{
    class TcpClient
    {
        // 服务端IP地址,本地测试使用127.0.0.1
        private static string serverIp = "127.0.0.1";
        // 服务端监听端口,需要和客户端一致
        private static int serverPort = 8888;

        static void Main(string[] args)
        {
            // 创建客户端Socket对象
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                // 连接服务端
                clientSocket.Connect(new IPEndPoint(IPAddress.Parse(serverIp), serverPort));
                Console.WriteLine($"已成功连接服务端{serverIp}:{serverPort}");

                // 开启异步接收服务端数据
                byte[] buffer = new byte[1024];
                clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, new object[] { clientSocket, buffer });

                // 循环读取用户输入并发送给服务端
                while (true)
                {
                    string sendMsg = Console.ReadLine();
                    if (string.IsNullOrEmpty(sendMsg))
                    {
                        continue;
                    }
                    if (sendMsg.ToLower() == "exit")
                    {
                        break;
                    }
                    byte[] sendData = Encoding.UTF8.GetBytes(sendMsg);
                    clientSocket.Send(sendData);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"连接服务端异常:{ex.Message}");
            }
            finally
            {
                // 断开连接时关闭Socket
                if (clientSocket.Connected)
                {
                    clientSocket.Shutdown(SocketShutdown.Both);
                }
                clientSocket.Close();
                Console.WriteLine("客户端已退出");
            }
        }

        // 接收服务端数据的回调函数
        static void ReceiveCallback(IAsyncResult ar)
        {
            object[] objs = (object[])ar.AsyncState;
            Socket clientSocket = (Socket)objs[0];
            byte[] buffer = (byte[])objs[1];
            try
            {
                int receiveLength = clientSocket.EndReceive(ar);
                if (receiveLength > 0)
                {
                    string receiveMsg = Encoding.UTF8.GetString(buffer, 0, receiveLength);
                    Console.WriteLine($"收到服务端消息:{receiveMsg}");

                    // 继续接收下一段数据
                    clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, new object[] { clientSocket, buffer });
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接收服务端数据异常:{ex.Message}");
            }
        }
    }
}

客户端进阶优化点

  • 添加断线重连机制,当检测到连接断开时,间隔一定时间尝试重新连接服务端,提升程序鲁棒性
  • 发送数据时添加队列机制,避免高频发送导致的数据冲突,同时可以在发送前对数据进行校验
  • 处理连接超时问题,设置SendTimeoutReceiveTimeout属性,避免无效等待

常见问题与解决方案

问题描述产生原因解决方案
服务端启动时报端口被占用该端口已被其他程序占用,或者上次程序退出未正确释放端口更换监听端口,或者在程序退出时确保调用Socket的Close方法释放端口
数据传输出现乱码服务端和客户端使用的编码格式不一致统一使用UTF8编码进行数据的序列化和反序列化
客户端发送长数据后服务端接收不完整TCP协议是流传输,会出现粘包拆包问题自定义通信协议,在数据包头部添加长度字段,接收端按长度拼接完整数据
客户端频繁断开重连导致服务端连接数暴涨客户端断开后服务端未正确检测到连接断开,未释放Socket资源添加心跳检测机制,同时服务端在接收数据长度为0时及时关闭对应Socket

使用注意事项

在实际生产环境中使用Socket通信时,还需要注意以下几点:

  • 所有Socket操作都需要放在try-catch块中,捕获SocketException等异常,避免程序崩溃
  • 高并发场景下可以使用SocketAsyncEventArgs替代Begin/End异步方法,减少线程切换开销,提升性能
  • 传输敏感数据时需要添加加密逻辑,比如使用AES加密传输内容,避免数据被窃听
  • 服务端需要限制单个IP的最大连接数,避免恶意连接攻击导致服务不可用

C#SocketTCP_IP服务端开发客户端开发修改时间:2026-06-18 06:42:57

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。