在C#中实现TCP/IP通信,最基础且常用的方式是通过System.Net.Sockets命名空间下的Socket类来完成,TCP协议作为面向连接的可靠传输协议,适合对数据完整性要求较高的场景。
TCP/IP通信核心概念
TCP/IP通信分为服务端和客户端两个角色,服务端需要先监听指定端口,等待客户端发起连接请求,连接建立后双方才能进行数据收发。C#中的Socket类封装了底层网络操作的细节,开发者不需要直接处理复杂的网络协议栈逻辑。
核心类说明
- Socket:实现网络通信的核心类,支持TCP、UDP等多种协议
- IPAddress:用于表示IP地址,可解析字符串形式的IP
- IPEndPoint:封装IP地址和端口号,作为网络连接的端点
TCP服务端实现步骤
服务端的核心流程是创建Socket、绑定端口、监听连接、接收客户端连接、收发数据、关闭连接,以下是完整的实现代码。
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace TcpServerDemo
{
class Program
{
static void Main(string[] args)
{
// 1. 创建Socket实例,使用IPv4、流套接字、TCP协议
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 2. 绑定IP和端口,这里绑定本地所有IP的8888端口
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 8888);
serverSocket.Bind(endPoint);
// 3. 开始监听,设置最大挂起连接数为10
serverSocket.Listen(10);
Console.WriteLine("服务端已启动,正在监听端口8888...");
// 4. 阻塞等待客户端连接,返回客户端的Socket实例
Socket clientSocket = serverSocket.Accept();
Console.WriteLine("客户端已连接:" + clientSocket.RemoteEndPoint.ToString());
// 5. 接收客户端发送的数据
byte[] receiveBuffer = new byte[1024];
int receiveLength = clientSocket.Receive(receiveBuffer);
string receiveMsg = Encoding.UTF8.GetString(receiveBuffer, 0, receiveLength);
Console.WriteLine("接收到客户端消息:" + receiveMsg);
// 6. 向客户端发送响应数据
string sendMsg = "服务端已收到你的消息";
byte[] sendBuffer = Encoding.UTF8.GetBytes(sendMsg);
clientSocket.Send(sendBuffer);
// 7. 关闭套接字释放资源
clientSocket.Close();
serverSocket.Close();
Console.WriteLine("通信结束,资源已释放");
}
}
}
TCP客户端实现步骤
客户端的流程相对简单,创建Socket后直接连接服务端端点,连接成功即可收发数据,以下是完整实现代码。
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace TcpClientDemo
{
class Program
{
static void Main(string[] args)
{
// 1. 创建Socket实例
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 2. 连接服务端,这里连接本地8888端口,实际使用时替换为目标服务端IP
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
clientSocket.Connect(serverEndPoint);
Console.WriteLine("已成功连接服务端");
// 3. 向服务端发送数据
string sendMsg = "你好,我是客户端";
byte[] sendBuffer = Encoding.UTF8.GetBytes(sendMsg);
clientSocket.Send(sendBuffer);
// 4. 接收服务端的响应数据
byte[] receiveBuffer = new byte[1024];
int receiveLength = clientSocket.Receive(receiveBuffer);
string receiveMsg = Encoding.UTF8.GetString(receiveBuffer, 0, receiveLength);
Console.WriteLine("接收到服务端响应:" + receiveMsg);
// 5. 关闭套接字
clientSocket.Close();
Console.WriteLine("客户端通信结束");
}
}
}
注意事项
在实际开发中,需要注意以下几点来保证通信的稳定性:
- 数据收发时需要使用统一的编码格式,避免中文乱码问题,示例中使用的是UTF8编码
- Socket操作属于IO操作,实际项目中建议使用异步方法(如
AcceptAsync、ReceiveAsync)避免阻塞主线程 - 接收数据时如果数据长度超过缓冲区大小,需要循环接收直到所有数据接收完成
- 使用完Socket后要及时调用
Close方法或者Dispose方法释放资源,避免端口占用 - 需要处理网络异常,比如连接断开、超时等情况,可添加try-catch逻辑捕获SocketException等异常
常见问题解答
连接服务端时提示端口被占用怎么办
如果服务端启动时提示端口被占用,可以更换一个未被占用的端口,或者检查是否有其他程序正在使用该端口,关闭对应程序后重新启动服务端即可。
如何同时处理多个客户端连接
要实现多客户端连接,可以在服务端接收到一个客户端连接后,将客户端的Socket交给新的线程或者异步任务处理,主线程继续监听新的连接请求,避免单个客户端阻塞整个服务端。