C# 网络编程:原始套接字、TCP 和 UDP 编程

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

原始套接字、TCP 和 UDP 编程

网络是现代软件系统的基石。无论您是构建聊天应用、多人游戏,还是高性能微服务架构,理解网络底层工作原理都至关重要。在本篇博文中,您将深入学习原始套接字、TCP 和 UDP 编程,掌握 C# 网络编程。阅读完本文后,您将拥有构建自定义服务器、处理网络协议以及创建高性能网络应用所需的知识和工具。

为什么要学习底层网络技术?

网络技术乍看之下可能令人望而生畏,但深入理解其基本原理能赋予你强大的开发能力。试想一下,你无需依赖第三方库或框架,就能构建自己的服务器。想象一下,你能够自信地调试棘手的网络问题,因为你了解底层原理。底层网络技术不仅仅是一项技能,更是对你职业生涯和解决复杂问题能力的投资。

什么是 Sockets**?**

网络编程的核心是套接字。你可以把套接字想象成一扇门,它允许数据在两台计算机之间流动。如果把互联网比作一栋巨大的公寓楼,那么套接字就是邻居们互相交流的门。套接字可以是:

  1. 面向连接的协议(TCP):确保两个端点之间可靠的通信。
  2. 无连接(UDP):速度更快但可靠性较低,常用于游戏或视频流等场景。

在 C# 中,System.Net.Sockets命名空间提供了处理套接字所需的所有工具。

TCP编程:建立可靠的连接

什么是TCP?

TCP(传输控制协议)就像打电话一样------建立连接,发送数据,并确保数据安全到达。它保证数据按顺序无误地到达。在 C# 中,您可以使用SocketTCPTcpClientTcpListener进行 TCP 编程。

创建 TCP 服务器

我们先来构建一个简单的TCP服务器。这个服务器会监听传入的连接,并将接收到的消息回显。

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

class TcpServer

{

static void Main()

{

const int port = 8888; // Port number to listen on

var listener = new TcpListener(IPAddress.Any, port);

Console.WriteLine($"Starting TCP Server on port {port}...");

listener.Start();

while (true)

{

Console.WriteLine("Waiting for a connection...");

var client = listener.AcceptTcpClient(); // Accept incoming connection

Console.WriteLine("Client connected!");

var stream = client.GetStream();

var buffer = new byte1024;

int bytesRead;

// Read and echo data

while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)

{

var message = Encoding.UTF8.GetString(buffer, 0, bytesRead);

Console.WriteLine($"Received: {message}");

// Echo back the message

stream.Write(buffer, 0, bytesRead);

Console.WriteLine("Message echoed back.");

}

client.Close();

Console.WriteLine("Client disconnected.");

}

}

}

代码要点

  1. TcpListener:监听指定端口上的传入连接。
  2. AcceptTcpClient:阻塞直到客户端连接。
  3. NetworkStream:用于读取和写入数据。

创建 TCP 客户端

现在,让我们创建一个 TCP 客户端来向服务器发送消息。

using System;

using System.Net.Sockets;

using System.Text;

class TcpClientExample

{

static void Main()

{

const string server = "127.0.0.1"; // Server address

const int port = 8888;

using var client = new TcpClient(server, port);

var stream = client.GetStream();

Console.WriteLine("Connected to server. Type messages to send:");

while (true)

{

var message = Console.ReadLine();

if (message == "exit") break;

var buffer = Encoding.UTF8.GetBytes(message);

stream.Write(buffer, 0, buffer.Length);

var responseBuffer = new byte1024;

var bytesRead = stream.Read(responseBuffer, 0, responseBuffer.Length);

var response = Encoding.UTF8.GetString(responseBuffer, 0, bytesRead);

Console.WriteLine($"Server response: {response}");

}

}

}

UDP编程:快速轻量级通信

什么是UDP?

用户数据报协议 (UDP) 就像寄明信片------虽然不能保证一定能送达,但它轻量且速度快。对于速度比可靠性更重要的场景,例如实时游戏或视频流,UDP 是理想之选。

创建UDP服务器

以下是如何构建一个简单的UDP服务器:

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

class UdpServer

{

static void Main()

{

const int port = 8888;

var udpClient = new UdpClient(port);

Console.WriteLine($"UDP Server started on port {port}...");

while (true)

{

var remoteEndpoint = new IPEndPoint(IPAddress.Any, 0);

var receivedBytes = udpClient.Receive(ref remoteEndpoint); // Receive data

var message = Encoding.UTF8.GetString(receivedBytes);

Console.WriteLine($"Received: {message} from {remoteEndpoint}");

var responseBytes = Encoding.UTF8.GetBytes("Message received!");

udpClient.Send(responseBytes, responseBytes.Length, remoteEndpoint); // Send response

}

}

}

创建UDP客户端

以下是一个与UDP服务器通信的客户端:

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

class UdpClientExample

{

static void Main()

{

var udpClient = new UdpClient();

const string server = "127.0.0.1";

const int port = 8888;

Console.WriteLine("Type messages to send:");

while (true)

{

var message = Console.ReadLine();

if (message == "exit") break;

var buffer = Encoding.UTF8.GetBytes(message);

udpClient.Send(buffer, buffer.Length, server, port);

var remoteEndpoint = new IPEndPoint(IPAddress.Any, 0);

var responseBytes = udpClient.Receive(ref remoteEndpoint);

var response = Encoding.UTF8.GetString(responseBytes);

Console.WriteLine($"Server response: {response}");

}

}

}

常见陷阱及避免方法

1.阻止调用

两者AcceptTcpClient都是Read阻塞式调用。如果处理不当,应用程序可能会卡死。为了获得更好的性能,请使用异步方法,例如 ` AcceptTcpClientAsync and` 和 `or` 。ReadAsync

2.缓冲区大小问题

务必确保缓冲区大小适合应用程序的需求。缓冲区太小,可能会导致数据截断;缓冲区太大,则会浪费内存。

3.错误处理

网络环境瞬息万变。连接可能会失败,数据可能会损坏,数据包可能会丢失。务必妥善处理此类异常SocketException情况IOException

4.安全性

切勿在未加密的情况下发送敏感数据。请使用 SSL/TLS 进行安全通信SslStream

要点总结

  • 套接字是网络编程的基础,它实现了机器之间的通信。
  • TCP 协议虽然可靠但速度较慢,因此非常适合对数据完整性要求较高的应用(例如文件传输)。
  • UDP 速度快但不可靠,适合游戏或流媒体等实时场景。
  • 异步编程可以提高性能并避免阻塞问题。
  • 错误处理和安全性对于生产级应用至关重要。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。