Socket 网络编程和IO模型
■ 选择(select); --- 稍微改进了一下,同时可以烧多壶时,小明一直循环的去看1号水壶有没有开,2号水壶有没有开,3号水壶..... 如果哪壶开了,就把那壶水倒进热水瓶。这样就不需要爸爸帮忙了,
2024-09-23 01:30:22 原文最近做了一个织机数据采集的服务器程序。
结构也非常简单,织机上的嵌入式设备,会通过Tcp 不停的往服务器发送一些即时数据。织机大改有个几十台到几百台不定把
刨去业务,先分析一下网络层的大概情况。每台织机发送数据的频率,我先假设每秒钟有个20次把。那就是50毫秒一次。
几百台客户端,每台每秒20来次的访问,对一个服务器来说,压力也算不大不小了把。
想想以前搞C++的时候用到过的IO模型,其实我也忘的差不多了,抱着温故知新的态度,再次梳理一下其中的差别。
这里有一个前提条件需要清楚。那就是CPU执行指令的速度很快,而IO操作的速度相对很慢。做一个Socket.Recv操作的时间,可能可以执行成百上千条 a++类似这样的语句()。
一个阻塞的Socket.Recv 就类似一个把水烧开倒进热水瓶的过程,Recv阻塞等待就好比等水烧开,有数据可读Recv返回数据 就好比 水烧开了倒水进热水瓶。
假设小明是一个cpu,在家他可能再看电视,看书,打扫,锻炼等,可以看成CPU同时执行多个程序。当小明需要烧一壶水时,可以比作做一个cpu 执行一个 Socket.Recv操作。
■ 同步(一个Socket连接起一个线程send/recv 。教科书常见); --相当于在烧水时,人一直再旁边看着等待水开,水开后就把开水倒进热水瓶。再去干其他看书,打扫等事。 。并且此时如果需要再烧一壶水,那么需要叫上爸爸去一直看着另一壶水,等水开。
■ 选择(select); --- 稍微改进了一下,同时可以烧多壶时,小明一直循环的去看1号水壶有没有开,2号水壶有没有开,3号水壶..... 如果哪壶开了,就把那壶水倒进热水瓶。这样就不需要爸爸帮忙了,但是,小明最多只能看个几十壶水,再多他就忙不过来了
■ 异步选择(WSAAsyncSelect); --又改进了一下,给水壶加了个哨子,水开的时候会呜呜响的那种,这样,小明就不用自己循环的去看哪壶水开没开,只要听呜呜声,哪壶响了就去哪壶倒水进热水瓶就行了。
■ 事件选择(WSAEventSelect);-- 和上面的类似,只不过不用勺子,用指示灯了,哪壶开了哪壶亮
- 上面的改进过程中,虽然小明不需要时时刻刻盯着水壶了,但是,水开后,小明还是得做一个动作,把水倒进热水壶--这个动作是比较花时间的。
■ 重叠I/O(Overlapped I/O); ----小明不想自己倒水了,发明了一个Overlapped的装置,只要把热水瓶装在这个装置上,然后把这个装置装到水壶上,等水开时,水就自动进热水瓶啦。
■ 完成端口(Completion Port) 。---- 后来小明家里开了热水厂,小明每天需要烧几万壶水-前面的模式都忙不过来啦,就买了一个高级的设备,它能同时烧几万壶水,也能把水自动灌进热水瓶
--以上,网络接收层只管到 把开水到进热水瓶。至于后面拿热水瓶的水去泡茶,还是冲咖啡,还是洗头, 那是业务层该做的事,
根据我的需求应该也就重叠IO和完成端口能胜任了把。
C/C++也有些日子没搞了有些生疏,于是抱着试试看的想法,用C# 的 Socket 来试试看。
C# 的 Socket 已经高度封装了,我随便拿了个TcpServer 类来玩,光看接口和用法我是完全看不出来它用的是啥IO模型.
但就是这么一个简简单单的异步读 BeginRead 。我测试用500个套接字,20毫秒发送一次。居然毫无压力。。。。他娘的当初我用winsock2搞 完成端口,那代码起码得几百行吧.
public void StartListen()
{
int port = int.Parse(listenPort);
TcpListener tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start(); while (true)
{
TcpClient client = tcpListener.AcceptTcpClient();//接受一个Client
NetworkStream networkStream = client.GetStream();
IPEndPoint remoteip = client.Client.RemoteEndPoint as IPEndPoint; byte[] buffer = new byte[buffersize];
SyncObj syncObj = new SyncObj()
{
tcpClient = client,
buffer = buffer };
IAsyncResult ret = networkStream.BeginRead(buffer, 0, buffersize, ReadAsyncCallback, syncObj);
} }
public void ReadAsyncCallback(IAsyncResult ar)
{
SyncObj syncObj = ar.AsyncState as SyncObj;
try
{
if (ar.IsCompleted)
{
NetworkStream networkStream = syncObj.tcpClient.GetStream();
int len = networkStream.EndRead(ar);
string msg = System.Text.Encoding.UTF8.GetString(syncObj.buffer,0, len);
Console.WriteLine(msg);
networkStream.BeginRead(syncObj.buffer, 0, buffersize, ReadAsyncCallback, syncObj); }
}
catch (System.IO.IOException ex)
{ syncObj.tcpClient.Close(); }
}
抱着疑惑,我查询了一些资料,发现C# 的异步,其实底层也是完成端口来搞的
http://blog.sina.com.cn/s/blog_494305f30100sb2n.html
并且C# 除了BeginXXX 类型的接口外,还有更高效的 XXXAsync 接口,见下方链接
Socket 网络编程和IO模型的更多相关文章
- Linux 网络编程(IO模型)
针对linux 操作系统的5类IO模型,阻塞式.非阻塞式.多路复用.信号驱动和异步IO进行整理,参考<linux网络编程>及相关网络资料. 阻塞模式 在socket编程(如下图)中调用如下 ...
- 网络编程基础--IO模型
一 IO模型介绍: 背景 是 Linux环境下 的 network IO , Third Edition: The Sockets Networking ”,.2节“I/O Models ”,Stev ...
- windows socket网络编程--事件选择模型
目录 事件选择模型概述 API详解 工作原理 代码实现 事件选择模型概述 Winsock提供了另一种有用的异步事件通知I/O模型--WSAEventSelect模型.这个模型与WSAAsyncSele ...
- Socket网络编程-IO各种概念及多路复用
Socket网络编程-IO各种概念及多路复用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.操作系统相关知识 1>.同步和异步 函数或方法被调用的时候,调用者是否得到最 ...
- Java Socket网络编程的经典例子(转)
事实上网络编程简单的理解就是两台计算机相互通讯数据而已,对于程序员而言,去掌握一种编程接口并使用一种编程模型相对就会显得简单的多了,Java SDK提供一些相对简单的Api来完成这些工作.Socket ...
- Socket网络编程--Libev库学习(1)
这一节是安装篇. Socket网络编程不知不觉已经学了快两个月了.现在是时候找个网络库学学了.搜索了很多关于如何学网络编程的博客和问答.大致都是推荐学一个网络库,至于C++网络库有那么几个,各有各的好 ...
- 基于Socket网络编程
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a2011480169/article/details/73602708 博客核心内容: 1.Sock ...
- Socket网络编程TCP、UDP演示样例
Socket网络编程: 1) OSI(了解): 国际标准化组织ISO(International Orgnization for Standardization)指定了网络通信的模型:开放系统互联(O ...
- Java Web 基础(一) 基于TCP的Socket网络编程
一.Socket简单介绍 Socket通信作为Java网络通讯的基础内容,集中了异常.I/O流模式等众多知识点.学习Socket通信,既能够了解真正的网络通讯原理,也能够增强对I/O流模式的理解. 1 ...
随机推荐
- Oracle-索引分裂研究
目录 索引分裂介绍 分类 索引分裂实验 基础环境准备 基础信息统计--之前 数据插入 基础信息统计--之后 Trace 数据统计 数据分析 索引PRI_ID之dba_extents视图 索引PRI_I ...
- C语言:交换两个变量的值
#include <stdio.h> int main() { int a,b; //方法一:借助第三个变量 int t; a=1,b=2; t=a; a=b; b=t; printf(& ...
- python删除文件中某一行
将文本中的 tasting123删除 with open("fileread.txt","r",encoding="utf-8") as f ...
- ES6新增语法(二)——函数和参数
箭头函数 箭头函数:将原来函数的function关键字和函数名都删掉,并使用"=>"连接参数列表和函数体. 箭头函数语法: (参数1,参数2)=>{ 函数体 } 注意点 ...
- WLS中Linux与Windows间的环境共享
Reference 更多cmd.exe帮助参考 (cmd_helps)[https://ss64.com/nt/cmd.html] (WSL备份,windows Docker安装)[https://w ...
- 【洛谷P1962 斐波那契数列】矩阵快速幂+数学推导
来提供两个正确的做法: 斐波那契数列双倍项的做法(附加证明) 矩阵快速幂 一.双倍项做法 在偶然之中,在百度中翻到了有关于斐波那契数列的词条(传送门),那么我们可以发现一个这个规律$ \frac{F_ ...
- 14Java进阶网络编程API
1.网络协议的三要素:语义.语法和时序 语义表示要做什么,语法表示要怎么做,时序表示做的顺序. 2.网络OSI七层模型 OSI/RM 模型(Open System Interconnection/Re ...
- 前端知识点--CSS overflow 属性
问题:如何加滚动条? 给div 设置css 样式overflow:scroll div { width:150px; height:150px; overflow:scroll; } -------- ...
- 如何使用SQL Server实现SignalR的横向扩展
一般来说,Web应用的扩展有两种:scale up(纵向扩展)和scale out(横向扩展). 1.纵向扩展 使用配置高(大内存,多处理器)的服务器或者虚拟机. 2.横向扩展 使用多个服务器(Web ...
- BSTestRunner增加历史执行记录展示和重试功能
之前对于用例的失败重试,和用例的历史测试记录存储展示做了很多的描述呢,但是都是基于各个项目呢,不方便使用,为了更好的使用,我们对这里进行抽离,抽离出来一个单独的模块,集成到BSTestRunner中, ...