C#实现TCP通信详解(附带实例)
TCP(Transmission Control Protocol)即传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。
在 C# 中,TCP 程序设计是指利用 Socket 类、TcpClient 类和 TcpListener 类编写的网络通信程序,这 3 个类都位于 System.Net.Sockets 命名空间中。
利用 TCP 进行通信的两个应用程序是有主次之分的,一个称为服务器端程序,另一个称为客户端程序。
Socket 类的常用属性及说明如下表所示。
Socket 类的常用方法及说明如下表所示。
可以使用下面两种方法之一连接到该侦听器:
TcpListener 类用于在同步阻止模式下侦听和接收传入的连接请求。可使用 TcpClient 类或 Socket 类来连接 TcpListener,并且可以使用 IPEndPoint、本地 IP 地址及端口号或者仅使用端口号来创建 TcpListener 实例对象。
TcpClient 类的常用属性、方法及说明如下表所示。
表:TcpClient类的常用属性、方法及说明
TcpListener 类的常用属性、方法及说明如下表所示。
创建客户端项目 Client,首先在 Main 方法中创建 TCP 连接对象,以指定的地址和端口连接服务器;然后向服务器端发送数据和接收服务器端传输的数据。代码如下:
客户端运行效果为:
在 C# 中,TCP 程序设计是指利用 Socket 类、TcpClient 类和 TcpListener 类编写的网络通信程序,这 3 个类都位于 System.Net.Sockets 命名空间中。
利用 TCP 进行通信的两个应用程序是有主次之分的,一个称为服务器端程序,另一个称为客户端程序。
C# Socket类
Socket 类为网络通信提供了一套丰富的方法和属性,主要用于管理连接,实现 Berkeley 通信端套接字接口,同时它还定义了绑定、连接网络端点及传输数据所需的各种方法,提供处理端点连接传输等细节所需要的功能。TcpClient 和 UdpClinet 等类在内部使用该类。Socket 类的常用属性及说明如下表所示。
| 属性 | 说明 |
|---|---|
| AddressFamily | 获取 Socket 的地址族 |
| Available | 获取已经从网络接收且可供读取的数据量 |
| Connected | 获取一个值,该值指示 Socket 是在上次 Send 还是 Receive 操作时连接到远程主机 |
| Handle | 获取 Socket 的操作系统句柄 |
| LocalEndPoint | 获取本地终结点 |
| ProtocolType | 获取 Socket 的协议类型 |
| RemoteEndPoint | 获取远程终结点 |
| SendTimeout | 获取或设置一个值,该值指定之后同步 Send 调用将超时的时间长度 |
Socket 类的常用方法及说明如下表所示。
| 方法 | 说明 |
|---|---|
| Accept | 为新建连接创建新的 Socket |
| BeginAccept | 开始一个异步操作来接受一个传入的连接尝试 |
| BeginConnect | 开始一个对远程主机连接的异步请求 |
| BeginDisconnect | 开始异步请求从远程终结点断开连接 |
| BeginReceive | 开始从连接的 Socket 中异步接收数据 |
| BeginSend | 将数据异步发送到连接的 Socket |
| BeginSendFile | 将文件异步发送到连接的 Socket |
| BeginSendTo | 向特定远程主机异步发送数据 |
| Close | 关闭 Socket 连接并释放所有关联的资源 |
| Connect | 建立与远程主机的连接 |
| Disconnect | 关闭套接字连接,并允许重用套接字 |
| EndAccept | 异步接收传入的连接尝试 |
| EndConnect | 结束挂起的异步连接请求 |
| EndDisconnect | 结束挂起的异步断开连接请求 |
| EndReceive | 结束挂起的异步读取 |
| EndSend | 结束挂起的异步发送 |
| EndSendFile | 结束文件的挂起异步发送 |
| EndSendTo | 结束挂起的、向指定位置进行的异步发送 |
| Listen | 将 Socket 置于侦听状态 |
| Receive | 接收来自绑定的 Socket 的数据 |
| Send | 将数据发送到连接的 Socket |
| SendFile | 将文件和可选数据异步发送到连接的Socket |
| SendTo | 将数据发送到特定的终结点 |
| Shutdown | 禁用某 Socket上的发送和接收 |
C# TcpClient类和TcpListener类
TcpClient 类用于在同步阻止模式下通过网络来连接、发送和接收流数据。为了使 TcpClient连 接并交换数据,TcpListener 实例或 Socket 实例必须侦听是否有传入的连接请求。可以使用下面两种方法之一连接到该侦听器:
- 创建一个 TcpClient,并调用 Connect 方法连接;
- 使用远程主机的主机名和端口号创建 TcpClient,此构造函数将自动尝试一个连接。
TcpListener 类用于在同步阻止模式下侦听和接收传入的连接请求。可使用 TcpClient 类或 Socket 类来连接 TcpListener,并且可以使用 IPEndPoint、本地 IP 地址及端口号或者仅使用端口号来创建 TcpListener 实例对象。
TcpClient 类的常用属性、方法及说明如下表所示。
表:TcpClient类的常用属性、方法及说明
| 属性及方法 | 说明 |
|---|---|
| Available 属性 | 获取已经从网络接收且可供读取的数据量 |
| Client 属性 | 获取或设置基础Socket |
| Connected 属性 | 获取一个值,该值指示TcpClient的基础Socket是否已连接到远程主机 |
| ReceiveBufferSize 属性 | 获取或设置接收缓冲区的大小 |
| ReceiveTimeout 属性 | 获取或设置在初始化一个读取操作后 TcpClient 等待接收数据的时间量 |
| SendBufferSize 属性 | 获取或设置发送缓冲区的大小 |
| SendTimeout 属性 | 获取或设置TcpClient等待发送操作成功完成的时间量 |
| BeginConnect 方法 | 开始一个对远程主机连接的异步请求 |
| Close 方法 | 释放此TcpClient实例,而不关闭基础连接 |
| Connect 方法 | 使用指定的主机名和端口号将客户端连接到TCP主机 |
| EndConnect 方法 | 异步接收传入的连接尝试 |
| GetStream 方法 | 返回用于发送和接收数据的NetworkStream |
TcpListener 类的常用属性、方法及说明如下表所示。
| 属性及方法 | 说明 |
|---|---|
| LocalEndpoint 属性 | 获取当前 TcpListener 的基础 EndPoint |
| Server 属性 | 获取基础网络 Socket |
| AcceptSocket/AcceptTcpClient 方法 | 接收挂起的连接请求 |
| BeginAcceptSocket/BeginAcceptTcpClient 方法 | 开始一个异步操作来接收一个传入的连接尝试 |
| EndAcceptSocket 方法 | 异步接收传入的连接尝试,并创建新的 Socket 来处理远程主机通信 |
| EndAcceptTcpClient 方法 | 异步接收传入的连接尝试,并创建新的 TcpClient 来处理远程主机通信 |
| Start 方法 | 开始侦听传入的连接请求 |
| Stop 方法 | 关闭侦听器 |
C# TCP网络程序实例
创建服务器端项目 Server,首先在 Main 方法中创建 TCP 连接对象;然后监听客户端接入,并读取接入的客户端 IP 地址和传入的消息;最后向接入的客户端发送一条信息,代码如下:
namespace Server
{
class Program
{
static void Main()
{
int port = 888; //端口
TcpClient tcpclient; //创建TCP连接对象
IPAddress[] serverIP = Dns.GetHostAddresses("127.0.0.1"); //定义IP地址
IPAddress localAddress = serverIP[0]; //IP地址
TcpListener tcpListener = new TcpListener(localAddress, port); //监听套接字
tcpListener.Start(); //开始监听
Console.WriteLine("服务器启动成功,等待用户接入…"); //输出消息
while (true)
{
try
{
//每接收一个客户端则生成一个TcpClient
tcpclient = tcpListener.AcceptTcpClient();
NetworkStream networkStream = tcpclient.GetStream(); //获取网络数据流
//定义流数据读取对象
BinaryReader reader = new BinaryReader(networkStream);
//定义流数据写入对象
BinaryWriter writer = new BinaryWriter(networkStream);
while (true)
{
try
{
string strReader = reader.ReadString(); //接收消息
//截取客户端消息
string[] strReaders = strReader.Split(new char[] { ',' });
//输出接收的客户端IP地址
Console.WriteLine("有客户端接入,客户IP:" + strReaders[0]);
//输出接收的消息
Console.WriteLine("来自客户端的消息:" + strReaders[1]);
string strWriter = "我是服务器,欢迎光临"; //定义服务器端要写入的消息
writer.Write(strWriter); //向对方发送消息
}
catch
{
break;
}
}
}
catch
{
break;
}
}
}
}
}
创建客户端项目 Client,首先在 Main 方法中创建 TCP 连接对象,以指定的地址和端口连接服务器;然后向服务器端发送数据和接收服务器端传输的数据。代码如下:
namespace Client
{
class Program
{
static void Main(string[] args)
{
//创建一个TcpClient对象,自动分配主机IP地址和端口号
TcpClient tcpclient = new TcpClient();
//连接服务器,其IP和端口号为127.0.0.1和888
tcpclient.Connect("127.0.0.1", 888);
if (tcpclient != null) //判断是否连接成功
{
Console.WriteLine("连接服务器成功");
NetworkStream networkStream = tcpclient.GetStream(); //获取数据流
BinaryReader reader = new BinaryReader(networkStream); //定义流数据读取对象
BinaryWriter writer = new BinaryWriter(networkStream); //定义流数据写入对象
string localip = "127.0.0.1"; //存储本机IP,默认值为127.0.0.1
IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName()); //获取所有IP地址
foreach (IPAddress ip in ips)
{
if (!ip.IsIPv6SiteLocal) //如果不是IPv6地址
localip = ip.ToString(); //获取本机IP地址
}
writer.Write(localip + ",你好服务器,我是客户端"); //向服务器发送消息
while (true)
{
try
{
string strReader = reader.ReadString(); //接收服务器发送的数据
if (strReader != null)
{
//输出接收的服务器消息
Console.WriteLine("来自服务器的消息:" + strReader);
}
}
catch
{
break; //接收过程中如果出现异常,则退出循环
}
}
}
Console.WriteLine("连接服务器失败");
}
}
}
首先运行服务器端,然后运行客户端,运行客户端后的服务器端效果为:
服务器启动成功,等待用户接入…
有客户端接入,客户IP:192.168.1.150
来自客户端的消息:你好服务器,我是客户端
客户端运行效果为:
连接服务器成功
来自服务器的消息:我是服务器,欢迎光临
ICP备案:
公安联网备案: