浏览目次:
基本
Socket编程
多线程并发
壅塞式同步IO
基本
在当今软件开发中,收集编程是异常重要的一部份,本文扼要引见下收集编程的观点和实践。
Socket是一种收集编程接口,它是对传输层TCP、UDP通讯协定的一层封装,经由过程友爱的API暴露出去,轻易在历程或多台机械间举行收集通讯。
Socket编程
在收集编程中分客户端和效劳端两种角色,比方经由过程翻开浏览器访问到挂在Web软件上的网页,从顺序角度上来看,即客户端(浏览器)提议了一个Socket要求到效劳器端,效劳器把网页内容返回到浏览器剖析后展现。在客户端和效劳端数据通讯前,会举行三次确认才会正式竖立衔接,也等于三次握手。
客户端发送音讯讯问效劳端是不是预备好
效劳端回应我预备好了,你呢预备好了吗
客户端回应效劳端我也预备好了,能够通讯了
TCP/IP协定是收集间通讯的基本协定,在差别编程语言及差别操纵体系下暴露的Socket接口用法也迥然差别,仅是其内部完成有所差别,比方Linux下的epoll和windows下的IOCP。
效劳端
实例化Socket
把大众地点端口绑定操纵体系上
最先监听绑定的端口
守候客户端衔接
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 6389); Socket listenSocket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listenSocket.Bind(ip); listenSocket.Listen(100); listenSocket.Accept();
listen函数中有个int范例参数,它示意最大守候处置惩罚衔接的数目,示意已竖立衔接但还未处置惩罚的数目,每挪用Accept函数一下即从这个守候行列中拿出一个衔接。 一般效劳端要效劳多个客户端要求的衔接,所以会轮回从守候行列中拿出衔接,举行吸收发送。
while (true) { var accept= listenSocket.Accept(); accept.Receive(); accept.Send(); }
多线程并发
上面的效劳端顺序处置惩罚吸收和发送音讯都是在当前线程下完成的,这意味着要处置惩罚完一个客户端衔接后才去处置惩罚下一个衔接,假如当前衔接是举行数据库或许文件读取写入等IO操纵,那会极大糟蹋效劳器的CPU资本,降低了效劳器吞吐量。
while (true) { var accept = listenSocket.Accept(); ThreadPool.QueueUserWorkItem((obj) => { byte[] receive = new byte[100]; accept.Receive(receive); byte[] send = new byte[100]; accept.Send(receive); }); }
如例子中,当监听到有新衔接要求过来时,挪用Accept()掏出当前衔接的socket,运用新的线程去处置惩罚吸收和发送信息,如许效劳端就可以完成并发处置惩罚多个客户端了。 上述代码中,在高并发下实际上是有题目标,假如客户端衔接要求不计其数个,那线程数目也会有这么多,每一个线程的栈空间都须要斲丧部份内存,再加上线程上下文切换,轻易致使效劳器负载太高,吞吐量大大下落,严峻时会引发宕机。 当前例子中运用体系ThreadPool的话,线程数目会固定在一个数目上,默许是1000,不会无限定开线程,会把处置惩罚超越线程数目标要求放到线程池中的行列上面。
在unix下相似的完成有2种:
fork一个新历程去处置惩罚客户端的衔接:
var connfd = Accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len); var m = fork(); if(m == 0) { //do something }
建立一个新的线程处置惩罚限流:
var *clientsockfd = accept(serversockfd,(struct sockaddr *)&clientaddress, (socklent *)&clientlen); if(pthreadcreate(&thread, NULL, recdata, clientsockfd)!=0) { //do something }
壅塞式同步IO
上述例子中运用的等于该模子,运用起来简朴轻易。
while (true) { var accept = listenSocket.Accept(); byte[] receive = new byte[100]; accept.Receive(receive); byte[] send = new byte[100]; accept.Send(receive); }
从挪用Receive函数起到接受到客户端发过来的数据时期,该函数会一向壅塞守候着,这个壅塞时期处置惩罚流程以下:
客户端发送数据
经由过程广域网局域网发送到效劳端机械网卡缓冲区上
网卡驱动对CPU发送中断指令
CPU把数据拷贝到内核缓冲区
CPU再把内核缓冲区的数据拷贝用户缓冲区,上面的receive字节数组。
至此处置惩罚胜利,最先处置惩罚下一个衔接要求。 挪用发送函数同样会壅塞在当前,然后把用户缓冲区(send字节数组)数据拷贝到内核中TCP发送缓冲区中。 TCP的发送缓冲区也有肯定的大小限定,假如发送的数据大于该限定,send函数会一向守候发送缓冲区有空闲时完整拷贝完才会返回,继承处置惩罚后续衔接要求。
异步IO
上篇提到用多线程处置惩罚多个壅塞同步IO而完成并发效劳端,这类形式在衔接数目比较小的时刻异常合适,一旦衔接过量,机能会急速下落。 在大多数效劳端收集软件中会采纳一种异步IO的体式格局来进步机能。
同步IO体式格局:衔接Receive要求->守候->守候->吸收胜利
异步IO体式格局:衔接Receive要求->马上返回->事宜或回调关照
采纳异步IO体式格局,意味着单线程能够处置惩罚多个要求了,衔接提议一个Receive要求后,当前线程能够马上去做别的事变,当数据吸收终了关照线程处置惩罚即可。
其数据吸收分2部份:
数据从别的机械发送内核缓冲区
内核缓冲区拷贝到用户缓冲区
第二部份示例代码:
byte[] msg = new byte[256]; socket.Receive(msg);
引见这2部份的目标是轻易辨别其他几种体式格局。 关于用户顺序来讲,同步IO和异步IO的区分在于第二部份是不是须要守候。
非壅塞式同步IO
非壅塞式同步IO,由同步IO延长出来,把这个名词拆分红2部份形貌:
非壅塞式,指的是上节"数据从别的机械发送内核缓冲区"部份黑白壅塞的。
同步IO,指的是上节"内核缓冲区拷贝到用户缓冲区"部份是守候的。
既然是第一部份黑白壅塞的,那就须要一种要领得知什么时刻内核缓冲区是OK的。 设置非壅塞形式后,在衔接挪用Receive要领时,会马上返回一个标记,示知用户顺序内核缓存区有没有数据,假如有数据最先举行第二部份操纵,从内核缓冲区拷贝到用户顺序缓冲区。 因为体系会返回个标记,那能够经由过程轮询体式格局来推断内核缓冲区是不是OK。
设置非壅塞形式参考代码:
SocketInformation sif=new SocketInformation(); sif.Options=SocketInformationOptions.NonBlocking; sif.ProtocolInformation = new byte[24]; Socket socket = new Socket(sif);
轮询参考代码:
while(true) { byte[] msg = new byte[256]; var temp = socket.Receive(msg); if (temp=="OK"){ //do something }else{ continue } }
这类体式格局近乎镌汰了,相识即可。
基于回调的异步IO
上面引见过:
异步IO体式格局:衔接Receive要求->马上返回->事宜或回调关照
当回调到执行时,数据已在用户顺序缓冲区已预备好了,在回调代码中对这部份数据举行响应的逻辑即可。
发出吸收要求:
static byte[] msg = new byte[256]; var temp = socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(ReadCallback), socket);
回调函数中对数据做处置惩罚:
public static void ReadCallback(IAsyncResult ar) { var socket = (Socket)ar.AsyncState; int read = socket.EndReceive(ar); DoSomething(msg); socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(Read_Callback), socket); }
当回调函数执行时,示意数据已预备好,须要先完毕吸收要求EndReceive,以便第二次发出吸收要求。 在效劳端顺序中要处置惩罚多个客户端的吸收,再次发出BeginReceive吸收数据要求即可。
这里的回调函数是在别的一个线程的触发,必要时要对数据加锁防备数据合作:
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
以上就是C#收集编程的图文代码详解的细致内容,更多请关注ki4网别的相干文章!