C# Socket网络通信【高并发场景】

用途

在 C# 中,Socket 类是用于在网络上进行低级别通信的核心类。它提供了对 TCP、UDP 等协议的支持,可以实现服务器和客户端之间的数据传输。Socket 提供了比 TcpClientUdpClient 等更细粒度的控制,因此通常用于需要更多控制的场景。

使用

服务器

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;class Server
{static void Main(){// 创建 SocketSocket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 绑定到本地 IP 和端口IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 11000);listener.Bind(localEndPoint);// 开始监听//服务器开始监听客户端连接,请求队列长度为 10,这意味着可以同时接受最多 10 个等待连接的客户端。listener.Listen(10);Console.WriteLine("等待客户端连接...");while (true) // 无限循环持续监听{// 接受客户端连接//会阻塞主线程,直到有客户端发起连接。这种设计确保了服务器能够同步处理每个客户端的连接。Socket handler = listener.Accept();Console.WriteLine("客户端已连接!");// 接收客户端发送的数据byte[] buffer = new byte[1024];int bytesRec = handler.Receive(buffer);Console.WriteLine("收到消息: " + Encoding.ASCII.GetString(buffer, 0, bytesRec));// 发送响应给客户端byte[] msg = Encoding.ASCII.GetBytes("消息已收到!");handler.Send(msg);// 关闭与客户端的连接handler.Shutdown(SocketShutdown.Both);handler.Close();}}
}

客户端

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;class Client
{static void Main(){// 创建 SocketSocket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 连接到服务器IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);sender.Connect(remoteEP);Console.WriteLine("已连接到服务器!");// 发送数据给服务器byte[] msg = Encoding.ASCII.GetBytes("Hello Server!");sender.Send(msg);// 接收服务器的响应byte[] buffer = new byte[1024];int bytesRec = sender.Receive(buffer);Console.WriteLine("服务器响应: " + Encoding.ASCII.GetString(buffer, 0, bytesRec));// 关闭连接sender.Shutdown(SocketShutdown.Both);sender.Close();}
}

服务器:Bind/Listen/Send/Close/
客户端:Connect/Send/Receive/

高并发场景

当前的服务器示例是单线程的,它只能顺序处理一个客户端的连接。一旦接受并处理了一个客户端的请求,才会继续监听下一个客户端的连接请求。

问题:
由于服务器是单线程的,它在处理某个客户端的连接时(调用 accept、receive 等),其他客户端的连接请求会被阻塞,直到当前请求完成。这意味着服务器无法并发处理多个客户端的请求。

解决方案:
为了使服务器能够并发处理多个客户端的连接,我们可以使用多线程或异步编程。

多线程实现:

通过为每个客户端连接创建一个独立的线程,服务器可以同时处理多个客户端。这样,每个客户端的请求都会在一个单独的线程中进行处理,主线程可以继续监听新的连接请求。

下面是修改后的代码,使用多线程来处理多个客户端的连接:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;class Server
{static void Main(){// 创建一个 TCP SocketSocket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 绑定到本地 IP 和端口IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 11000);listener.Bind(localEndPoint);// 开始监听连接请求,队列长度为10listener.Listen(10);Console.WriteLine("服务器正在监听客户端连接...");while (true) // 无限循环持续监听{// 接受客户端连接Socket handler = listener.Accept();Console.WriteLine("客户端已连接!");// 为每个客户端连接创建一个新线程Thread clientThread = new Thread(() => HandleClient(handler));clientThread.Start();}}// 处理客户端连接的逻辑static void HandleClient(Socket clientSocket){try{// 接收客户端发送的数据byte[] buffer = new byte[1024];int bytesRec = clientSocket.Receive(buffer);Console.WriteLine("收到消息: " + Encoding.ASCII.GetString(buffer, 0, bytesRec));// 发送响应给客户端byte[] msg = Encoding.ASCII.GetBytes("消息已收到!");clientSocket.Send(msg);}finally{// 关闭与客户端的连接clientSocket.Shutdown(SocketShutdown.Both);clientSocket.Close();}}
}

在每次有新的客户端连接时,服务器会调用 listener.Accept() 接受连接,然后为这个连接创建一个新的线程。
新线程会执行 HandleClient 方法,在该方法中处理客户端的通信(接收消息、发送响应等)。
并发处理:

服务器主线程通过 while (true) 持续监听客户端的连接请求。
每次有客户端连接时,服务器会创建一个新的线程处理该连接,这样主线程不会被阻塞,可以继续接受其他客户端的连接请求。
线程处理客户端:
HandleClient 方法会在线程中执行,处理特定客户端的通信。
在该线程中,服务器接收客户端的数据并发送响应,最后关闭连接。
多线程的优缺点:

  • 优点:
    • 能够同时处理多个客户端的连接,提升服务器的并发能力。
    • 每个客户端的请求处理相互独立,不会因为某个客户端的处理时间过长而阻塞其他客户端的连接。
  • 缺点:
    • 每个客户端连接都创建一个新线程,随着客户端数量的增加,可能会消耗大量的系统资源(如 CPU 和内存)。
    • 线程的创建和销毁是有开销的,在高并发场景下,可能不够高效。

异步编程实现:

在 C# 中,还可以使用异步编程(async/await)来处理多个客户端的连接,避免创建大量线程。异步方法允许服务器在等待 I/O 操作(如 Receive、Send)完成时,不会阻塞主线程,具有更好的扩展性。

异步服务器示例:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;class Server
{static async Task Main(){// 创建一个 TCP SocketSocket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 绑定到本地 IP 和端口IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 11000);listener.Bind(localEndPoint);// 开始监听连接请求,队列长度为10listener.Listen(10);Console.WriteLine("服务器正在监听客户端连接...");while (true){// 异步接受客户端连接Socket handler = await Task.Factory.FromAsync(listener.BeginAccept, listener.EndAccept, null);Console.WriteLine("客户端已连接!");// 异步处理客户端连接_ = Task.Run(() => HandleClient(handler));}}// 处理客户端连接的逻辑static async Task HandleClient(Socket clientSocket){try{byte[] buffer = new byte[1024];// 异步接收客户端发送的数据int bytesRec = await Task.Factory.FromAsync(clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, null, null),clientSocket.EndReceive);Console.WriteLine("收到消息: " + Encoding.ASCII.GetString(buffer, 0, bytesRec));// 异步发送响应给客户端byte[] msg = Encoding.ASCII.GetBytes("消息已收到!");await Task.Factory.FromAsync(clientSocket.BeginSend(msg, 0, msg.Length, SocketFlags.None, null, null),clientSocket.EndSend);}finally{// 关闭与客户端的连接clientSocket.Shutdown(SocketShutdown.Both);clientSocket.Close();}}
}

异步编程的优缺点:

  • 优点:
    • 异步编程模型更高效,因为它不需要为每个客户端连接创建新的线程。【而是通过申请线程池中的线程来完成任务】
    • 能够处理大量并发请求而不会消耗太多系统资源。
  • 缺点:
    • 代码复杂度较高,需要熟悉异步编程模型和 async/await 语法。

总结:

  • 单线程:示例中初始的服务器是单线程的,只能顺序处理一个客户端的连接请求。无法并发处理多个客户端。
  • 多线程:可以通过为每个客户端连接创建一个新线程来实现并发处理,能够处理多个客户端,但线程的创建和销毁有开销。
  • 异步编程:通过异步方法来处理客户端连接,在处理 I/O 操作时不会阻塞线程,能够处理大量并发请求,且资源消耗较低。

如果你的服务器需要处理大量并发请求,异步编程模型可能是更优的选择。如果并发量较小,多线程方式也是一个有效的方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/427961.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

arcgisPro地理配准

1、添加图像 2、在【影像】选项卡中,点击【地理配准】 3、 点击添加控制点 4、选择影像左上角格点,然后右击填入目标点的投影坐标 5、依次输入四个格角点的坐标 6、点击【变换】按钮,选择【一阶多项式(仿射)】变换 7…

1.Seata 1.5.2 seata-server搭建

一:Seata基本介绍 Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 详见官网链接:https://seata.apache.org/zh-cn/ 1.历史项目里的使用经验: 之前公司里的oem用户对应的App…

多重指针变量(n重指针变量)实例分析

0 前言 指针之于C语言,就像子弹于枪械。没了子弹的枪械虽然可以用来肉搏,却失去了迅速解决、优雅解决战斗的能力。但上了膛的枪械也非常危险,时刻要注意是否上了保险,使用C语言的指针也是如此,要万分小心,…

【VUE3.0】动手做一套像素风的前端UI组件库---先导篇

系列文章目录 【VUE3.0】动手做一套像素风的前端UI组件库—Button 目录 系列文章目录引言准备素材字体鼠标手势图 创建vue3项目构建项目1. 根据命令行提示选择如下:2. 进入项目根目录下载依赖并启动。3. 设置项目src路径别名,方便后期应用路径。4. 将素…

solana项目counter,测试过程中执行报错记录分享

跟随HackQuest部署counter项目,使用 Solana 官方提供的 playgroud 。这个平台让我们的部署和测试过程变得更加简便高效。 合约代码 lib.rs中复制以下代码 use anchor_lang::prelude::*; use std::ops::DerefMut;declare_id!("CVQCRMyzWNr8MbNhzjbfPu9YVvr97…

Amoco:一款针对二进制源码的安全分析工具

关于Amoco Amoco是一款功能强大的二进制源码静态分析工具,该工具基于Python 3.8开发,可以帮助广大研究人员轻松对二进制程序执行静态符号分析。 工具特性 1、一个通用的指令解码框架,旨在减少实现对新架构的支持所需的时间。例如&#xff0c…

通过springcloud gateway优雅的进行springcloud oauth2认证和权限控制

代码地址 如果对你有帮助请给个start,本项目会持续更新,目标是做一个可用的快速微服务开发平台,成为接私活,毕设的开发神器, 欢迎大神们多提意见和建议 使用的都是spring官方最新的版本,版本如下&#xff1…

F12抓包11:UI自动化 - Recoder(记录器)

课程大纲 使用场景(导入和导出): ① 测试的重复性工作,本浏览器录制并进行replay; ② 导入/导出录制脚本,移植后replay; ③ 导出给开发进行replay复现bug; ④ 进行前端性能分析。 1、录制脚…

Virtuoso服务在centos中自动停止的原因分析及解决方案

目录 前言1. 问题背景2. 原因分析2.1 终端关闭导致信号12.2 nohup命令的局限性 3. 解决方案3.1 使用 screen 命令保持会话3.2 使用 tmux 作为替代方案3.3 使用系统服务(systemd) 4. 其他注意事项4.1 网络配置4.2 日志监控 结语 前言 在使用Virtuoso作为…

mybatisplus映射与数据库表格不一致问题

1.字段映射与属性名不一致 TableField(value"数据库字段名") 2.entity添加了数据库表格不存在的属性 TableField(existfalse) 3.entity对象查询时,有些字段不想要显示在查询结果上 TableField(selectfalse) 4.表名不一致 TableName("数据库表名&…

爬虫--翻页tips

免责声明:本文仅做分享! 伪线程 from DrissionPage import ChromiumPage import timepage ChromiumPage() page.get("https://you.ctrip.com/sight/taian746.html") # 初始化 第0页 index_page 0# 翻页点击函数 sleep def page_turn():page…

使用API有效率地管理Dynadot域名,为域名进行隐私保护设置

前言 Dynadot是通过ICANN认证的域名注册商,自2002年成立以来,服务于全球108个国家和地区的客户,为数以万计的客户提供简洁,优惠,安全的域名注册以及管理服务。 Dynadot平台操作教程索引(包括域名邮箱&…

八股文-多线程、并发

八股文-多线程、并发 最近学到了一种方法,可以用于简历项目经验编写以及面试题目的回答 STAR法则:在什么背景下,你需要解决什么问题,你做了啥,得到了什么结果 情境(Situation): 描…

电子元件制造5G智能工厂物联数字孪生平台,推进制造业数字化转型

5G智能工厂与物联数字孪生平台的融合应用,不仅为电容器制造业注入了新的活力,更为整个制造业的数字化转型树立了新的标杆。电子元件制造过程中,数字孪生平台通过实时监测生产线的各个环节,实现了生产流程的可视化监控。管理人员可…

苹果M4 MacBook Air被曝2025Q1发布 屏幕面板10月出货

9 月 20 日最新消息屏幕供应链咨询公司 DSCC 首席执行官罗斯・杨(Ross Young)昨日(9 月 19 日)在 X 平台面向其订阅用户发布推文,透露苹果 M4 MacBook Air 与低成本 iPad 的屏幕预估将于今年 10 月开始出货。 苹果正在…

海外盲盒APP为盲盒出海助力,拓展海外市场

潮玩市场是一个具有全球化的行业在全球都具有非常高的发展潜力,随着国内盲盒市场的饱和,拓展海外市场对盲盒企业至关重要。近年来,盲盒已经在海外市场取得了一定的成绩,这为企业拓展海外市场奠定了发展基础。 目前,在…

基于FPGA+GPU异构平台的遥感图像切片解决方案

随着遥感和成像技术的不断进步和普及,获取大量高分辨率的遥感图像已成为可能。这些大规模的遥感图像数据需要进行有效的处理和分析,以提取有用的信息,进行进一步的应用。遥感图像切片技术应运而生,该技术可以将大型遥感图像分割成…

[苍穹外卖]-10WebSocket入门与实战

WebSocket WebSocket是基于TCP的一种新的网络协议, 实现了浏览器与服务器的全双工通信, 即一次握手,建立持久连接,双向数据传输 区别 HTTP是短连接, WebSocket是长连接HTTP单向通信, 基于请求响应模型WebSocket支持双向通信 相同 HTTP和WebSocket底层都是TCP连接 应用场景…

Go语言练习——语法实践

目录 一、数组 1.多维数组的声明和使用 2.数组与切片的转换 3.数组在函数中的使用 二、切片 1.切片的动态扩容机制 2.切片的复制与修改 3.切片在排序算法中的应用 三、结构体 1.结构体的嵌套与方法 2.结构体与JSON的序列化 3.结构体的工厂模式 四、映射 1.映射的并发访问 2.映射…

SEGGERS实时系统embOS推出Linux端模拟器

SEGGER 发布了两个新的 embOS 仿真模拟器:embOS Sim Linux 和 embOS-MPU Sim Linux。 通过模拟 Linux 主机系统上的硬件,取代物理硬件,为开发人员提供了一种无缝的方式来构建原型和测试应用程序。 embOS Sim Linux 端口支持 32 位和 64 位系…