目录
1.Socket,TCP,UDP
1.1Socket通信:
Socket是更底层的网络通信接口,不仅支持TCP,也支持UDP等其他传输协议。它为网络通信提供了基本的构建块,允许开发者直接操作IP地址和端口,进行低级的数据读写操作。
TcpClient
和TcpListener
实际上就是对Socket API的封装,使得开发者可以在不需要详细了解Socket编程的情况下使用TCP进行通信。可以说,TcpClient
和TcpListener
是Socket通信在TCP协议上的具体应用。
1.2TCP通信:
TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层协议。它通过三次握手建立连接,确保数据按序无误地传输,并通过四次挥手断开连接。
TcpClient和TcpListener是.NET框架中对TCP协议的高级抽象,简化了使用TCP进行网络通信的复杂度。TcpClient
面向客户端,用于连接服务器并发送/接收数据;TcpListener
面向服务端,用于监听特定端口上的连接请求并处理这些连接。
1.3UDP通信:
UDP(User Datagram Protocol)是另一种传输层协议,与TCP相对,它是无连接的、不可靠的、基于数据报的。UDP不保证数据的顺序和到达,但它的优势在于头部开销小,传输速度快,适用于实时应用如在线视频、VoIP等。
在.NET中,UdpClient类是对UDP协议的高级封装,提供了发送和接收UDP数据报的功能,类似于TcpClient
对于TCP的作用,但不涉及连接的建立和维护,因为UDP本身就是无连接的。
总结,TcpClient
和TcpListener
是实现TCP通信的高级工具,它们建立在Socket通信的基础之上,提供了更方便的API来处理TCP连接。而TCP通信和UDP通信是两种不同的传输层协议,分别适用于需要可靠性和速度、实时性不同需求的场景。Socket通信则是更底层的通信方式,支撑了上述所有基于特定协议的网络通信。
2.TcpClient TcpListener
TCP(Transmission Control Protocol)是互联网中一种面向连接的、可靠的、基于字节流的传输层通信协议。在.NET框架中,TcpClient
和TcpListener
类为开发者提供了实现TCP通信的便捷方式。
TcpListener
TcpListener
类用于在服务器端监听指定的IP地址和端口号上的连接请求。它允许服务器应用程序等待并接受来自客户端的连接。一旦接受到连接请求,TcpListener
会创建一个新的TcpClient
实例来处理这个连接。
基本用法
- 创建TcpListener实例:首先,需要指定要监听的IP地址和端口号。
- 开始监听:调用
Start()
方法开始监听连接请求。 - 接受连接:使用
AcceptTcpClient()
阻塞等待直到有客户端连接,然后返回一个TcpClient
对象来与客户端通信。 - 关闭监听:完成任务后,应调用
Stop()
方法停止监听。
TcpClient
TcpClient
类用于在客户端建立到远程主机的TCP连接,并通过这个连接发送或接收数据。它提供了读写流(GetStream()
方法返回的NetworkStream)来处理数据交换。
基本用法
- 创建TcpClient实例:可以直接创建,也可以通过服务器返回的连接实例化。
- 连接到服务器:调用
Connect()
方法,传入服务器的IP地址和端口号以建立连接。 - 数据交换:通过
GetStream()
得到的NetworkStream进行读写操作。 - 关闭连接:完成数据交换后,调用
Close()
方法关闭连接。
示例:简单聊天应用
实现客户端和服务器端双向通信。
服务器端代码(TcpListener)
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class Server
{
public static void StartServer()
{
TcpListener listener = new TcpListener(IPAddress.Any, 8888);
Console.WriteLine("服务器正在启动...");
listener.Start();
Console.WriteLine("服务器已启动,等待客户端连接...");
while (true)
{
TcpClient client = listener.AcceptTcpClient();
Console.WriteLine("客户端已连接");
// 使用线程来处理每个客户端,以便同时处理多个连接
Thread t = new Thread(() => HandleClient(client));
t.Start();
}
}
private static void HandleClient(TcpClient client)
{
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[1024];
string data;
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
data = Encoding.ASCII.GetString(buffer, 0, read);
Console.WriteLine($"接收到消息: {data}");
if (data.ToLower() == "exit")
{
break;
}
// 回显消息给客户端
byte[] response = Encoding.ASCII.GetBytes(data);
stream.Write(response, 0, response.Length);
// 发送一条新消息给客户端
string serverMessage = "这是服务器的消息";
byte[] serverData = Encoding.ASCII.GetBytes(serverMessage);
stream.Write(serverData, 0, serverData.Length);
}
client.Close();
Console.WriteLine("客户端已断开连接");
}
}
class Program
{
static void Main(string[] args)
{
Server.StartServer();
}
}
客户端代码(TcpClient)
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
public class Client
{
public static void SendMessage()
{
TcpClient client = new TcpClient("localhost", 8888);
Console.WriteLine("已连接到服务器");
NetworkStream stream = client.GetStream();
while (true)
{
Console.Write("请输入消息 (输入'exit'退出): ");
string message = Console.ReadLine();
if (message.ToLower() == "exit")
{
break;
}
byte[] data = Encoding.ASCII.GetBytes(message);
stream.Write(data, 0, data.Length);
// 读取服务器的消息
byte[] buffer = new byte[1024];
int read = stream.Read(buffer, 0, buffer.Length);
string serverResponse = Encoding.ASCII.GetString(buffer, 0, read);
Console.WriteLine($"服务器回应: {serverResponse}");
}
client.Close();
Console.WriteLine("已断开与服务器的连接");
}
}
class Program
{
static void Main(string[] args)
{
Client.SendMessage();
}
}
在这个示例中,服务器端为每个连接的客户端创建一个新线程来处理读写操作,这样可以同时服务多个客户端。客户端和服务器之间实现了双向通信,即客户端发送消息给服务器,服务器回显该消息并额外发送一条自己的消息给客户端,客户端接收并显示这些消息。同样,当任意一端输入"exit"时,将结束当前连接。