C# Socket TCP编程实现客户端与服务端通信
掌握C#中的Socket网络编程是实现分布式应用的关键。本文将详细解析如何利用System.Net.Sockets命名空间下的核心类,搭建一个简单的TCP服务端与客户端通信模型,涵盖监听、连接、数据传输及资源释放等关键步骤。
使用 TcpListener 构建服务端
服务端的核心任务是监听特定端口并等待客户端连接。为了实现基础的同步阻塞式监听,我们可以使用 TcpListener 类。在初始化时指定监听端口(例如 9000),调用 Start() 方法后,程序将进入一个无限循环以接受新的连接请求。
重要提示:在实际生产环境中,直接使用 AcceptTcpClient() 会阻塞主线程导致界面卡顿或服务无响应。必须采用异步编程模式(Async/Await)或多线程技术来处理并发连接,以下示例展示了多线程处理的思路。
第1步:启动服务端监听
首先实例化 TcpListener 对象并启动服务。代码如下:
class Program
{
static void Main(string[] args)
{
// 创建 TcpListener 实例,监听 9000 端口
TcpListener lsner = new TcpListener(9000);
lsner.Start();
Console.WriteLine("started in port: 9000");
while (true)
{
// AcceptTcpClient 是一个阻塞调用,直到有客户端连接才返回
TcpClient client = lsner.AcceptTcpClient();
Console.WriteLine("new client received. hashcode: {0}", client.GetHashCode());
// 使用线程池执行任务,避免阻塞主监听循环
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessTcpClient), client);
}
// 实际应用中应添加退出机制或信号量控制
// Console.ReadKey();
}
}
第2步:处理单个客户端连接
当有新的客户端连接进入时,我们在子线程中处理该连接的数据流。通过获取 NetworkStream,可以使用 StreamWriter 向客户端发送简单的文本数据。数据处理完毕后,务必关闭流和客户端连接以释放资源。
private static void ProcessTcpClient(object state)
{
TcpClient client = state as TcpClient;
if (client == null)
{
Console.WriteLine("client is null");
return;
}
try
{
// 获取网络的输入输出流
NetworkStream ns = client.GetStream();
// 写入数据
StreamWriter sw = new StreamWriter(ns);
sw.WriteLine("Welcome.");
sw.Flush(); // 确保缓冲区的数据被发送
sw.Close();
// 清理资源
client.Close();
}
catch (Exception ex)
{
Console.WriteLine($"Process error: {ex.Message}");
client?.Close();
}
}
使用 TcpClient 建立客户端
客户端的作用是与已知地址和端口的服务端建立连接,并从中读取数据。主要使用 TcpClient 类进行连接管理,并通过 StreamReader 读取服务端发送的数据流。
第3步:连接服务端并接收数据
在客户端程序中,我们需要定义目标服务器的 IP 地址和端口号,然后发起连接。连接成功后,创建读取流并接收服务端发出的消息。完成后,需要依次关闭网络流和客户端对象,防止内存泄漏。
class Program
{
static void Main(string[] args)
{
try
{
// 定义服务端地址和端口
IPAddress address = IPAddress.Parse("127.0.0.1");
IPEndPoint ep = new IPEndPoint(address, 9000);
// 创建客户端并发起连接
TcpClient client = new TcpClient();
client.Connect(ep);
// 获取流并进行读取
NetworkStream ns = client.GetStream();
StreamReader sr = new StreamReader(ns);
string message = sr.ReadToEnd();
Console.WriteLine(message); // 输出: Welcome.
// 按正确顺序释放资源
sr.Close();
sr.Dispose();
ns.Close();
ns.Dispose();
client.Close();
}
catch (Exception ex)
{
Console.WriteLine($"Connection failed: {ex.Message}");
}
finally
{
Console.ReadKey();
}
}
}
运行验证与排错
- 启动顺序:必须先运行服务端代码,确保监听窗口显示 "started in port: 9000" 后,再启动客户端代码。
- 防火墙设置:如果客户端运行在其他机器上,请确保服务端所在机器的防火墙已放行 TCP 9000 端口。
- 超时异常:若服务端未启动就运行客户端,
Connect方法可能抛出AegisException或连接超时异常,建议在代码中使用try-catch块捕获此类异常以提高程序的健壮性。
总结
C# 提供的 TcpListener 和 TcpClient 类简化了底层 Socket 的编程复杂度。本示例清晰地展示了如何在一个简单的一对一通信场景中完成数据握手与传输。对于更复杂的实时通信需求,建议进一步探索 SocketsHttpHandler、异步套接字封装或结合 WebSocket 协议以提升性能。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













