C#使用TcpListener与TcpClient实现简单聊天通信
本文将详细讲解如何在C# Windows Forms应用中实现一个基础的点对点聊天程序。核心逻辑包括服务器端的端口监听(TcpListener)与线程处理,以及客户端的连接(TcpClient)和数据流读写操作。文中将提供关键的代码片段说明具体的参数配置与方法调用。
核心原理与准备条件
要实现简单的文本聊天功能,需要明确两个角色的职责:服务器端负责持续监听特定IP和端口,等待客户端连接;客户端负责发起连接请求并发送数据。整个过程依赖于TCP协议的可靠连接特性。
- 依赖库:必须引入
System.Net.Sockets,System.Net,System.IO, 以及System.Threading命名空间。 - 关键类:
TcpListener:用于监听传入的连接请求。TcpClient:用于连接服务器或作为已连接的实例进行数据传输。NetworkStream:表示底层的网络数据流,所有IO操作都基于此流。BinaryReader/BinaryWriter:方便地读取和写入字符串等数据类型。
- 运行顺序:启动服务器监听 → 客户端发起连接 → 双方通过流进行读写。
第1步:搭建服务器端ChatServer
服务器端的主要任务是开启监听并接受连接。由于接受连接和处理消息是阻塞操作,建议使用独立线程执行,以免界面卡顿。
1.1 初始化与配置
定义端口、IP地址及核心网络组件变量。以下示例使用了固定IP和端口号54321,实际部署时可改为动态获取本机IP。
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;
public class ChatServer
{
private int port = 54321; // 监听端口
// 注意:实际应用中建议使用 Dns.GetHostName() 获取本机IP或 IPAddress.Any
private IPAddress ip = IPAddress.Parse("10.20.30.40");
private TcpListener tcpListener = null;
private TcpClient tcpClient = null;
private NetworkStream networkStream = null;
private BinaryReader reader;
private string getAllMsg = ""; // 用于存储接收到的消息
}
1.2 启动监听服务
在WinForm窗体的“开始监听”按钮点击事件中,实例化 TcpListener 并开始监听。同时创建一个新线程来处理客户端的接入请求。
// 假设这是界面上“开始监听”按钮的单击事件
private void btnStartListen_Click(object sender, EventArgs e)
{
// 绑定IP和端口
tcpListener = new TcpListener(ip, port);
// 开始监听
tcpListener.Start();
// 创建专门用于接受客户端消息的线程
Thread acceptClientMsgThread = new Thread(AcceptClientMsg);
// 设置为后台线程,防止程序意外退出导致主线程阻塞
acceptClientMsgThread.IsBackground = true;
acceptClientMsgThread.Start();
}
1.3 接受连接与读取消息
AcceptTcpClient 是一个阻塞方法,会一直等待直到有客户端连接。一旦连接建立,即可获取网络流并进行循环读取。
private void AcceptClientMsg()
{
try
{
// 等待并接受一个客户端连接
tcpClient = tcpListener.AcceptTcpClient();
if (tcpClient != null)
{
// 获取网络流
networkStream = tcpClient.GetStream();
// 创建二进制读取器
reader = new BinaryReader(networkStream);
// 循环读取客户端发来的信息
while (true)
{
// ReadString 会自动读取长度前缀后跟随的字符串
string msg = reader.ReadString();
getAllMsg += msg;
// 注意:在实际WinForm应用中,跨线程更新UI需要使用Invoke
// txtShowClientMsg.Text = getAllMsg;
}
}
}
catch (Exception ex)
{
// 记录异常或提示用户断开
Console.WriteLine(ex.Message);
}
}
若服务器需要回复客户端,需在确保已获取到 networkStream 的前提下,实例化 BinaryWriter 并调用 Write 方法:
// 发送消息示例
string sendMsg = "Hello Client";
BinaryWriter writer = new BinaryWriter(networkStream);
writer.Write(sendMsg); // 需先调用 Flush()
第2步:搭建客户端ChatClient
客户端的核心功能是连接服务器,并通过同一根网络流进行双向通信。需要注意的是,TcpClient 实例既用于连接也用于维持状态。
2.1 发起连接
实例化 TcpClient 后,调用 Connect 方法指向服务器的IP和端口。成功后立即获取 NetworkStream。
using System.Net.Sockets;
using System.Net;
using System.IO;
public class ChatClient
{
private int port = 54321;
private IPAddress ip = IPAddress.Parse("10.20.30.40");
private TcpClient tcpClient = null;
private NetworkStream networkStream = null;
private BinaryWriter writer;
// private BinaryReader reader; // 如果需要接收服务端消息则解开注释
}
2.2 建立连接动作
对应窗体上的“连接服务器”按钮:
private void btnStartConnect_Click(object sender, EventArgs e)
{
try
{
tcpClient = new TcpClient();
// 连接到指定IP和端口
tcpClient.Connect(ip, port);
// 获取网络流,用于后续读写
networkStream = tcpClient.GetStream();
}
catch (Exception ex)
{
MessageBox.Show("连接失败: " + ex.Message);
}
}
2.3 发送消息
连接稳定后,初始化 BinaryWriter 并发送文本。注意:由于 BinaryWriter 和 BinaryReader 共享底层流,如果两端都有收发消息需求,需分别实例化对应的读/写对象。
private void btnSend_Click(object sender, EventArgs e)
{
// 假设获取输入框内容
string sendMsg = txtSendMsg.Text;
if (!string.IsNullOrEmpty(sendMsg) && networkStream != null)
{
// 如果未初始化writer,在此处初始化
if (writer == null)
{
writer = new BinaryWriter(networkStream);
}
// 发送字符串
writer.Write(sendMsg);
writer.Flush(); // 确保数据写入缓冲区
// 清空输入框
txtSendMsg.Clear();
}
}
完成判断与注意事项
连接成功判定:
1. 服务器端 btnStartListen_Click 无报错抛出。
2. 客户端 btnStartConnect_Click 执行完毕,且未进入Catch块。
3. 此时客户端发出的消息会在服务器端的 getAllMsg 变量或UI控件中体现。
潜在问题排查:
- 防火墙拦截:确保服务器所在主机允许端口(如54321)入站流量。
- IP地址匹配:客户端填写的IP必须是服务器当前有效的本地IP(内网测试通常用127.0.0.1或局域网IP),而非公网IP,否则在局域网调试时会连接超时。
- 并发限制:上述简易示例仅支持单客户端连接。若需多客户端,服务器端需在 AcceptClientMsg 外部循环调用 AcceptTcpClient 并为每个新连接分配独立的线程。
以上就是基于C# Socket编程实现简单聊天程序的详细内容,更多关于C# TcpListener与TcpClient网络通信的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













