-
C#网络编程生态(.NET BCL、第三方库)
第一部分:网络编程基础
第1章 网络编程核心概念
1.3 C#网络编程生态(.NET BCL、第三方库)
一、为什么要了解C#网络编程生态?
之前做实时聊天系统,一开始用.NET BCL的TcpListener自己写,写了两周才实现基本功能,后来发现第三方库SuperSocket已经封装好了所有功能,只用了一天就完成了。选对工具,能让你少走90%的弯路。这节就带你梳理C#网络编vb.net教程C#教程python教程SQL教程access 2010教程程的完整生态,从.NET官方的BCL类库到主流第三方库,结合实战代码,让你知道什么时候用官方库,什么时候用第三方库。
二、.NET BCL:官方原生网络编程工具集
BCL(Base Class Library)是.NET的基础类库,包含了所有官方原生的网络编程API,是C#网络编程的“基石”。
-
核心命名空间与类
命名空间 核心类/接口 用途
System.Net IPAddress、IPEndPoint、Dns IP地址处理、域名解析
System.Net.Sockets Socket、TcpListener、TcpClient、UdpClient 底层Socket、TCP/UDP编程
System.Net.Http HttpClient、HttpResponseMessage HTTP/HTTPS编程
System.Net.WebSockets ClientWebSocket、WebSocket WebSocket编程
System.Net.NetworkInformation NetworkInterface、Ping 网络状态检测、Ping功能
C#实战:用BCL实现TCP服务器
csharp
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace BclTcpServer;
class Program
{
static async Task Main(string[] args)
{
// 1. 创建TcpListener,绑定IP地址和端口
var ipAddress = IPAddress.Any; // 监听所有本地IP地址
int port = 8888;
var listener = new TcpListener(ipAddress, port);
try
{
// 2. 启动监听
listener.Start();
Console.WriteLine($"TCP服务器已启动,监听端口:{port}");
while (true)
{
// 3. 接受客户端连接(异步非阻塞)
var client = await listener.AcceptTcpClientAsync();
Console.WriteLine($"客户端已连接:{client.Client.RemoteEndPoint}");
// 4. 处理客户端请求(用Task.Run避免阻塞主线程)
_ = Task.Run(() => HandleClientAsync(client));
}
}
catch (Exception ex)
{
Console.WriteLine($"服务器异常:{ex.Message}");
}
finally
{
// 5. 停止监听
listener.Stop();
}
}
static async Task HandleClientAsync(TcpClient client)
{
using (client)
{
// 获取网络流(用于读写数据)
var stream = client.GetStream();
var buffer = new byte[1024];
try
{
// 读取客户端发送的数据
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine($"收到客户端消息:{message}");
// 发送响应给客户端
string response = $"服务器已收到消息:{message}";
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
await stream.WriteAsync(responseBytes, 0, responseBytes.Length);
Console.WriteLine($"已发送响应给客户端:{response}");
}
catch (Exception ex)
{
Console.WriteLine($"处理客户端请求异常:{ex.Message}");
}
}
}
}
代码逐行讲:
1.TcpListener:官方封装的TCP服务器类,底层基于Socket,简化了TCP服务器的开发;
2.IPAddress.Any:监听所有本地IP地址(包括IPv4的0.0.0.0和IPv6的::);
3.AcceptTcpClientAsync:异步接受客户端连接,不会阻塞主线程,支持高并发;
4.HandleClientAsync:处理单个客户端的请求,用using自动释放TcpClient资源;
5.NetworkStream:TCP通信的核心流,用于读写数据,底层自动处理TCP的可靠传输。
2. BCL的优缺点
优点:
原生支持:不需要安装任何第三方库,直接使用;
稳定可靠:经过微软官方严格测试,适合生产环境;
文档完善:有官方文档和大量示例,学习成本低。
缺点:
底层繁琐:如果用Socket直接开发,需要处理很多底层细节(如粘包、拆包);
功能有限:对于复杂场景(如WebSocket服务器、高并发TCP服务器),需要自己封装很多功能;
性能一般:官方封装的类为了通用性,性能不如一些优化过的第三方库。
三、第三方库:提升开发效率的“利器”
对于复杂场景,第三方库能帮你节省大量时间,以下是C#网络编程的主流第三方库。
-
SuperSocket:高性能TCP/UDP服务器框架
核心特点:
高性能:基于IOCP(完成端口),支持百万级并发连接;
易扩展:支持自定义协议、过滤器、命令;
功能丰富:内置粘包处理、心跳检测、会话管理;
开源免费:MIT协议,可自由修改和商用。
C#实战:用SuperSocket实现TCP服务器
前置条件:安装NuGet包SuperSocket.Server(.NET 6+)
csharp
using System;
using System.Text;
using Microsoft.Extensions.Hosting;
using SuperSocket;
using SuperSocket.ProtoBase;
namespace SuperSocketTcpServer;
class Program
{
static async Task Main(string[] args)
{
// 1. 创建主机,配置SuperSocket
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
// 注册SuperSocket服务,指定协议为TextPackage(文本协议)
services.AddSuperSocket<TcpPackageInfo, TextPipelineFilter>();
})
.Build();
// 2. 启动服务器
await host.StartAsync();
Console.WriteLine("SuperSocket TCP服务器已启动,按任意键退出...");
Console.ReadKey();
// 3. 停止服务器
await host.StopAsync();
}
}
// 自定义数据包类型
public class TcpPackageInfo : IPackageInfo
{
public string Key { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
}
// 自定义协议过滤器(处理粘包、拆包)
public class TextPipelineFilter : FixedHeaderPipelineFilter<TcpPackageInfo>
{
public TextPipelineFilter() : base(2) // 头部长度为2字节
{
}
// 解析头部,获取包体长度
protected override int GetBodyLengthFromHeader(ReadOnlySequence<byte> buffer)
{
var header = buffer.Slice(0, 2);
return BitConverter.ToInt16(header.ToArray());
}
// 解析包体,生成数据包
protected override TcpPackageInfo DecodePackage(ReadOnlySequence<byte> buffer)
{
var body = buffer.Slice(2); // 跳过头部
string bodyStr = Encoding.UTF8.GetString(body);
string[] parts = bodyStr.Split(new[] { "|" }, 2);
return new TcpPackageInfo
{
Key = parts[0],
Body = parts.Length > 1 ? parts[1] : string.Empty
};
}
}
// 自定义命令处理器
public class EchoCommand : IAsyncCommand<TcpPackageInfo>
{
public async ValueTask ExecuteAsync(IAppSession session, TcpPackageInfo package)
{
Console.WriteLine($"收到客户端消息:Key={package.Key}, Body={package.Body}");
// 发送响应给客户端
string response = $"Echo: {package.Body}";
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
// 构造响应包:2字节头部(包体长度)+ 包体
byte[] header = BitConverter.GetBytes((short)responseBytes.Length);
await session.SendAsync(header.Concat(responseBytes).ToArray());
}
}
代码逐行讲:
1.AddSuperSocket:注册SuperSocket服务,指定数据包类型和协议过滤器;
2.FixedHeaderPipelineFilter:固定头部协议过滤器,自动处理粘包、拆包(头部2字节表示包体长度);
3.IAsyncCommand:自定义命令处理器,根据数据包的Key自动路由到对应的命令;
4.IAppSession:会话管理,包含客户端连接信息、发送/接收方法;
5.对比BCL的TcpListener:SuperSocket已经封装了粘包处理、会话管理、命令路由,开发效率提升10倍以上。
2. HttpClientFactory:HTTP客户端的“最佳实践”
核心特点:
连接池管理:自动管理HTTP连接池,避免频繁创建和销毁连接;
依赖注入:支持.NET Core的依赖注入,易于测试和扩展;
配置灵活:支持超时、重试、日志、拦截器;
性能优化:内置HTTP/2支持,提升并发性能。
C#实战:用HttpClientFactory实现HTTP客户端
前置条件:.NET 6+
csharp
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace HttpClientFactoryExample;
class Program
{
static async Task Main(string[] args)
{
// 1. 创建主机,配置HttpClientFactory
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
// 注册命名HttpClient,配置基础地址和超时
services.AddHttpClient("BaiduClient", client =>
{
client.BaseAddress = new Uri("https://www.baidu.com/");
client.Timeout = TimeSpan.FromSeconds(10);
})
// 添加重试策略
.AddPolicyHandler(PolicyExtensions.GetRetryPolicy());
})
.Build();
// 2. 获取HttpClient实例
var httpClient = host.Services.GetRequiredService<IHttpClientFactory>().CreateClient("BaiduClient");
// 3. 发送HTTP请求
try
{
var response = await httpClient.GetAsync("");
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"HTTP响应长度:{content.Length}");
}
catch (Exception ex)
{
Console.WriteLine($"HTTP请求异常:{ex.Message}");
}
// 4. 停止主机
await host.StopAsync();
}
}
// 重试策略扩展类
public static class PolicyExtensions
{
public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
.Or<HttpRequestException>()
.WaitAndRetryAsync(3, retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
}
代码逐行讲:
1.AddHttpClient:注册命名HttpClient,配置基础地址、超时、重试策略;
2.GetRetryPolicy:用Polly库实现重试策略(需要安装NuGet包Polly);
3.CreateClient:从工厂获取HttpClient实例,工厂自动管理连接池和生命周期;
4.对比原生HttpClient:原生HttpClient如果频繁创建会导致连接泄漏,HttpClientFactory自动管理连接池,性能提升明显。
3. SignalR:实时双向通信框架
核心特点:
实时双向通信:支持服务器主动向客户端推送消息;
多协议支持:支持WebSocket、Server-Sent Events、Long Polling;
跨平台:支持.NET、JavaScript、Java、Python等客户端;
功能丰富:内置分组、用户认证、消息广播。
C#实战:用SignalR实现实时聊天服务器
前置条件:安装NuGet包Microsoft.AspNetCore.SignalR(.NET 6+)
服务器端代码:
csharp
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
namespace SignalRChatServer;
public class ChatHub : Hub
{
// 客户端调用此方法发送消息
public async Task SendMessage(string user, string message)
{
// 广播消息给所有客户端
await Clients.All.SendAsync("ReceiveMessage", user, message);
Console.WriteLine($"收到消息:{user} -> {message}");
}
// 客户端连接时触发
public override async Task OnConnectedAsync()
{
Console.WriteLine($"客户端已连接:{Context.ConnectionId}");
await base.OnConnectedAsync();
}
// 客户端断开连接时触发
public override async Task OnDisconnectedAsync(Exception? exception)
{
Console.WriteLine($"客户端已断开:{Context.ConnectionId}");
await base.OnDisconnectedAsync(exception);
}
}
class Program
{
static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// 注册SignalR服务
builder.Services.AddSignalR();
var app = builder.Build();
// 配置SignalR路由
app.MapHub<ChatHub>("/chatHub");
app.Run("http://localhost:5000");
}
}
客户端代码(WPF):
前置条件:安装NuGet包Microsoft.AspNetCore.SignalR.Client
csharp
using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Windows;
namespace SignalRChatClient;
public partial class MainWindow : Window
{
private HubConnection _connection;
public MainWindow()
{
InitializeComponent();
// 创建SignalR连接
_connection = new HubConnectionBuilder()
.WithUrl("http://localhost:5000/chatHub")
.Build();
// 注册接收消息的方法
_connection.On<string, string>("ReceiveMessage", (user, message) =>
{
Dispatcher.Invoke(() =>
{
MessagesListBox.Items.Add($"{user}: {message}");
});
});
}
private async void ConnectButton_Click(object sender, RoutedEventArgs e)
{
try
{
await _connection.StartAsync();
ConnectButton.IsEnabled = false;
SendButton.IsEnabled = true;
MessageBox.Show("连接成功!");
}
catch (Exception ex)
{
MessageBox.Show($"连接失败:{ex.Message}");
}
}
private async void SendButton_Click(object sender, RoutedEventArgs e)
{
try
{
string user = UserTextBox.Text;
string message = MessageTextBox.Text;
await _connection.InvokeAsync("SendMessage", user, message);
MessageTextBox.Clear();
}
catch (Exception ex)
{
MessageBox.Show($"发送失败:{ex.Message}");
}
}
}
代码逐行讲:
1.Hub:SignalR的核心类,定义客户端和服务器之间的通信方法;
2.Clients.All.SendAsync:广播消息给所有客户端,也可以用Clients.User发送给指定用户,Clients.Group发送给指定分组;
3.HubConnection:客户端连接类,自动处理WebSocket、Server-Sent Events、Long Polling的切换;
4._connection.On:注册客户端接收消息的方法,服务器调用SendAsync时会触发此方法;
5.对比原生WebSocket:SignalR已经封装了连接管理、消息序列化、重连机制,开发效率提升10倍以上。
4. 其他主流第三方库
| 库名称 | 用途 | 特点 |
|---|---|---|
| MQTTnet | MQTT协议客户端/服务器 | 轻量级、低功耗,适合IoT场景 |
| Grpc.Net.Client | gRPC客户端/服务器 | 高性能、跨语言,适合微服务通信 |
| RestSharp | RESTful API客户端 | 易使用、功能丰富,支持OAuth2 |
| FluentFTP | FTP客户端/服务器 | 支持FTP、FTPS、SFTP,功能丰富 |
| WireSharkSharp | 网络抓包与协议解析 | 基于WireShark,支持多种协议 |
四、如何选择合适的工具?
| 场景 | 推荐工具 |
|---|---|
| 简单TCP/UDP客户端/服务器 | .NET BCL(TcpListener、UdpClient) |
| 高并发TCP/UDP服务器 | SuperSocket、DotNetty |
| HTTP/HTTPS客户端 | HttpClientFactory、RestSharp |
| 实时双向通信(聊天、推送) | SignalR、WebSocketSharp |
| IoT设备通信 | MQTTnet |
| 微服务通信 | gRPC、SignalR |
| FTP/SFTP文件传输 | FluentFTP |
五、基础知识拓展
-
IOCP(完成端口)是什么?
IOCP是Windows操作系统的一种异步IO模型,能高效处理大量并发IO操作,是高性能网络服务器的核心。SuperSocket、DotNetty等第三方库都是基于IOCP实现的。
核心原理:
操作系统维护一个完成端口队列,当IO操作完成时,把结果放入队列;
服务器用少量线程从队列中取出结果,处理IO操作;
避免了传统同步IO模型中每个连接一个线程的资源浪费,支持百万级并发连接。 -
粘包、拆包是什么?
在TCP通信中,数据是以“流”的形式传输的,没有边界,可能出现以下情况:
粘包:多个数据包被合并成一个数据包发送;
拆包:一个数据包被拆分成多个数据包发送;
解决方法:
固定长度协议:每个数据包的长度固定;
分隔符协议:用特殊字符(如 )作为数据包的分隔符;
头部长度协议:数据包头部包含包体长度,如SuperSocket的FixedHeaderPipelineFilter。 -
心跳检测是什么?
在TCP通信中,如果客户端异常断开连接(如网络中断、程序崩溃),服务器可能不知道客户端已经断开,导致资源浪费。心跳检测就是客户端定期向服务器发送一个小数据包,服务器如果在指定时间内没有收到心跳包,就认为客户端已经断开,释放资源。
实现方法:
客户端每隔一段时间发送一个心跳包;
服务器维护一个心跳超时时间,如果超过时间没有收到心跳包,就断开连接;
SuperSocket、SignalR等第三方库已经内置了心跳检测功能。
六、总结:选对工具,事半功倍
.NET BCL:适合简单场景,是学习网络编程的基础,必须掌握;
第三方库:适合复杂场景,能帮你节省大量时间,提升开发效率;
选择原则:优先用官方库,官方库满足不了需求再用第三方库;
学习建议:先掌握官方库的底层原理,再学习第三方库的封装思想,这样才能在遇到问题时快速定位和解决。
比如你要做一个高并发TCP服务器,先用官方库的Socket自己实现一个,理解IOCP、粘包处理、心跳检测的原理,再用SuperSocket实现,这样你不仅会用第三方库,还能理解它的底层实现,遇到问题时能快速排查。下一节我们就用官方库实现第一个C#网络程序:TCP客户端与服务器。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49510.html










