C#基于Sockets类实现TCP通讯的具体代码
本文详细介绍如何使用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)。 - 端口占用:如果启动服务端时报错,请确认所选端口未被其他程序占用。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













