16人参与 • 2026-09-16 • Asp.net
在网络编程中,tcp(transmission control protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在 c# 桌面应用开发中,基于 winform 实现 tcp 客户端与服务端通信是非常常见的需求,例如局域网聊天工具、远程控制、数据采集上报等场景。
本文将带领大家从零开始,使用 c# 和 winform 分别实现一个 tcp 服务端与客户端,涵盖连接管理、消息收发、异常处理等核心知识点,并附上完整可运行的示例代码。
tcpdemo,选择目标框架后点击「创建」。在 .net 中,tcp 编程主要依赖 system.net.sockets 命名空间下的以下核心类:
| 类名 | 说明 |
|---|---|
tcplistener | 服务端监听客户端连接请求 |
tcpclient | 客户端连接服务端,或服务端接受连接后得到的客户端对象 |
networkstream | 网络数据流,用于读写数据 |
streamreader / streamwriter | 基于文本的流读写辅助类 |
在 winform 窗体上拖入以下控件:
textbox(端口号输入框,命名为 txtport)button(启动/停止监听按钮,命名为 btnstart)textbox(消息输入框,命名为 txtmsg)button(发送按钮,命名为 btnsend)listbox 或 richtextbox(日志显示区域,命名为 lstlog)using system;
using system.net;
using system.net.sockets;
using system.text;
using system.threading;
using system.windows.forms;
namespace tcpdemo
{
public partial class serverform : form
{
private tcplistener _listener;
private tcpclient _client;
private networkstream _stream;
private thread _listenthread;
private thread _receivethread;
private bool _isrunning;
public serverform()
{
initializecomponent();
}
private void btnstart_click(object sender, eventargs e)
{
if (!_isrunning)
{
startserver();
}
else
{
stopserver();
}
}
private void startserver()
{
try
{
int port = int.parse(txtport.text.trim());
_listener = new tcplistener(ipaddress.any, port);
_listener.start();
_isrunning = true;
btnstart.text = "停止监听";
appendlog($"服务端已启动,监听端口:{port}");
_listenthread = new thread(listenclient);
_listenthread.isbackground = true;
_listenthread.start();
}
catch (exception ex)
{
messagebox.show("启动失败:" + ex.message);
}
}
private void listenclient()
{
while (_isrunning)
{
try
{
// 阻塞等待客户端连接
_client = _listener.accepttcpclient();
appendlog($"客户端已连接:{_client.client.remoteendpoint}");
_stream = _client.getstream();
// 启动接收线程
_receivethread = new thread(receivedata);
_receivethread.isbackground = true;
_receivethread.start();
}
catch (exception ex)
{
if (_isrunning)
{
appendlog("监听异常:" + ex.message);
}
}
}
}
private void receivedata()
{
byte[] buffer = new byte[1024];
try
{
while (_isrunning && _client.connected)
{
int length = _stream.read(buffer, 0, buffer.length);
if (length > 0)
{
string msg = encoding.utf8.getstring(buffer, 0, length);
appendlog($"收到客户端消息:{msg}");
}
}
}
catch (exception ex)
{
appendlog("接收数据异常:" + ex.message);
}
}
private void btnsend_click(object sender, eventargs e)
{
if (_stream == null || !_client.connected)
{
messagebox.show("没有客户端连接");
return;
}
string msg = txtmsg.text.trim();
if (string.isnullorempty(msg))
{
return;
}
byte[] data = encoding.utf8.getbytes(msg);
_stream.write(data, 0, data.length);
appendlog($"发送消息:{msg}");
txtmsg.clear();
}
private void stopserver()
{
_isrunning = false;
try
{
_stream?.close();
_client?.close();
_listener?.stop();
}
catch (exception ex)
{
appendlog("关闭异常:" + ex.message);
}
btnstart.text = "启动监听";
appendlog("服务端已停止");
}
private void appendlog(string msg)
{
if (lstlog.invokerequired)
{
lstlog.invoke(new action<string>(appendlog), msg);
}
else
{
lstlog.items.add($"[{datetime.now:hh:mm:ss}] {msg}");
}
}
private void serverform_formclosing(object sender, formclosingeventargs e)
{
stopserver();
}
}
}
客户端窗体控件布局:
textbox(服务端 ip 输入框,命名为 txtip)textbox(端口号输入框,命名为 txtport)button(连接/断开按钮,命名为 btnconnect)textbox(消息输入框,命名为 txtmsg)button(发送按钮,命名为 btnsend)listbox(日志显示区域,命名为 lstlog)using system;
using system.net.sockets;
using system.text;
using system.threading;
using system.windows.forms;
namespace tcpdemo
{
public partial class clientform : form
{
private tcpclient _client;
private networkstream _stream;
private thread _receivethread;
private bool _isconnected;
public clientform()
{
initializecomponent();
}
private void btnconnect_click(object sender, eventargs e)
{
if (!_isconnected)
{
connectserver();
}
else
{
disconnectserver();
}
}
private void connectserver()
{
try
{
string ip = txtip.text.trim();
int port = int.parse(txtport.text.trim());
_client = new tcpclient();
_client.connect(ip, port);
_stream = _client.getstream();
_isconnected = true;
btnconnect.text = "断开连接";
appendlog($"已连接服务端:{ip}:{port}");
_receivethread = new thread(receivedata);
_receivethread.isbackground = true;
_receivethread.start();
}
catch (exception ex)
{
messagebox.show("连接失败:" + ex.message);
}
}
private void receivedata()
{
byte[] buffer = new byte[1024];
try
{
while (_isconnected && _client.connected)
{
int length = _stream.read(buffer, 0, buffer.length);
if (length > 0)
{
string msg = encoding.utf8.getstring(buffer, 0, length);
appendlog($"收到服务端消息:{msg}");
}
}
}
catch (exception ex)
{
appendlog("接收数据异常:" + ex.message);
}
}
private void btnsend_click(object sender, eventargs e)
{
if (!_isconnected || _stream == null)
{
messagebox.show("尚未连接服务端");
return;
}
string msg = txtmsg.text.trim();
if (string.isnullorempty(msg))
{
return;
}
byte[] data = encoding.utf8.getbytes(msg);
_stream.write(data, 0, data.length);
appendlog($"发送消息:{msg}");
txtmsg.clear();
}
private void disconnectserver()
{
_isconnected = false;
try
{
_stream?.close();
_client?.close();
}
catch (exception ex)
{
appendlog("断开异常:" + ex.message);
}
btnconnect.text = "连接服务端";
appendlog("已断开连接");
}
private void appendlog(string msg)
{
if (lstlog.invokerequired)
{
lstlog.invoke(new action<string>(appendlog), msg);
}
else
{
lstlog.items.add($"[{datetime.now:hh:mm:ss}] {msg}");
}
}
private void clientform_formclosing(object sender, formclosingeventargs e)
{
disconnectserver();
}
}
}
8888),点击「启动监听」。127.0.0.1)和端口号 8888,点击「连接服务端」。接收数据的线程属于后台线程,不能直接操作 ui 控件,必须通过 invoke 或 begininvoke 封送到 ui 线程执行,示例代码中的 appendlog 方法已做处理。
tcp 是字节流协议,多次发送的数据可能被合并接收(粘包),也可能一次发送的数据被拆成多次接收(拆包)。对于简单示例,可以约定以特定字符(如 \n)作为消息结束符,或自定义消息头声明数据长度。
在实际项目中,客户端可能因网络异常而断开,服务端无法及时感知。建议客户端定时发送心跳包,服务端超时未收到心跳则判定连接失效并清理资源。
当客户端强制关闭时,服务端 read 方法会抛出异常或返回 0,应在此处释放资源并更新连接状态。
本文通过一个完整的 winform 示例,演示了 c# 中 tcp 服务端与客户端的基本开发流程。核心要点包括:
tcplistener 监听端口,通过 accepttcpclient 接受连接。tcpclient 主动连接服务端。networkstream 进行读写。invoke 实现跨线程更新 ui。在此基础上,读者可以进一步扩展多客户端并发处理、消息分包协议、心跳保活、断线重连等功能,构建更健壮的网络应用。
到此这篇关于使用c# winform实现一个tcp服务端与客户端的文章就介绍到这了,更多相关c# winform tcp客户端与服务端内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论