第十八章SOCKET类的实现_第1页
第十八章SOCKET类的实现_第2页
第十八章SOCKET类的实现_第3页
第十八章SOCKET类的实现_第4页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第十八章 SOCKET类的实现 这几天反复思考,到底是从上到下、还是从底层开始往上设计?最后、还是决定从上层建筑开始。APO追求的是简单、再简单!强大、再强大!高速、高效!“天下武功、无坚不破、唯快不破!”。 APO的socket也不外是一种内存文件吧,但socket描述符和其它类型的文件描述符还是略有区别的。APO中的一个用户进程最多可打开64K个非socket类型的文件描述符,而APO系统只是最多可以打开16M个v节点,需要256个64K位的位图变量、刚好1个位图变量数据块;中模式管理。socket描述符也是在16M个文件描述符中分配,APO中的socket描述符、描述的是一个连接、可以说

2、是连接号,与UNIX可能会有一点不同;理论上、APO可以在一个服务端口上最大支持1千6百多万个连接。APO的网络编程是非常简单的,如服务端程序、只是在初始化方法中open一个socket,余下的只是对各种连接消息的处理方法的编写。即使有1千万个连接,那又能怎样?对于它们的请求消息的处理方法都是一样的。用户无须关心打开了多少socket描述符,有多少连接,关闭连接,TCP/UDP、管理socket描述符等等,那都是用户系统网络进程的事情。对于用户的网络编程,我们就是要越简单越好。服务端程序只是关心、来了一个带请求的连接消息,需要处理该请求消息,使用消息中的socket描述符就可操作该连接对应的接

3、收、或发送流容器;至于、该连接是如何建立起来的、当前是否有1千万个连接等等,不用管的。 LINUX、WINSOCKET中的bind()、socket()、listen()、accept()、connect()、write()、read()、recvfrom()、sendto()、upds_respon()、recv()、send()、recvmsg()、sendmsg()、close、shutdoen()、循环服务器、并发服务器、多路I/O复用、原始套接字等等、我都看晕了,这难道是给应用程序员使用的网络编程方法库?我只能感叹!真垃圾!这是底层程序员使用的、不是应用程序员啊。发展了几十年,应该是

4、精华的浓缩了;为何我总看不顺眼?总感觉这样做、复杂、效率低,为何聪明人总是把问题复杂化啊?我也很想兼容和适应它们,但总是有心无力;自己笨、没法把握他们的思路。不管怎样,服务端支持千万个连接的功能我是加定了;这样,1000个游戏服务器就可支持100亿人同时在线了。 在APO中,网络编程是分为三层:第一层SOCKET应用层,第二层是TCP/UDP(用户CPU线路的系统网络服务进程)、第三层是最底层IP/ICMP(内核CPU线路的实时线程)。层之间是使用消息交互、句柄提交、事件驱动。后2层是系统实现,用户主要是使用第一层编程。SOCKET是一种内存文件,网络编程分为服务端和客户端,网络协议主要就是T

5、CP/UDP;在open文件SOCKET时、就需指明。open、close本来就是文件系统的基本方法,本文只是描述与socket有关的内容。数据报接收是2、3层自动实现的,包含数据报内容的句柄就是相应socket连接的文件号sockfd,以消息方式提交给用户进程;用户只需使用sockfd.成员的赋值指令,就可对接收的数据报进行读、写。不同的文件号sockfd句柄、对应不同的连接,有不同的内存容器。只要本地内存空间够大,支持千万个连接就没问题。内存分配是无须用户去考虑,只要给出规划就行了。为何?当我们编写一个客户端程序时,无法预先知道你请求之后、服务器返回的数据报大小,可能2GB;也就无法一开始

6、就声明接收流容器的本地内存空间大小。但接收到服务器返回的数据报后,底层知道;所以、就可由底层申请分配内存,并将句柄关联到相应的sockfd。那接收就似乎无须用户规划了,但你发送的请求数据报是可以预设大小的。如果客户端,请求一个4GB大小的文件,难道服务器就要即时申请一个连续4GB大小的内存空间?用户编写的服务端程序无须这样麻烦,只是向2层发一个消息就行了(sendto()、一切2层搞掂。或许APO在SOCKET层就3个方法了:open()、close()、sendto()。前2个本来就是文件系统的基本方法,open()方法的参数有所不一样吧;所以改为opens()。用户程序主要是编写消息处理;

7、实现HTTP协议、FTP等等。其实、即使这些协议的实现;APO操作系统都包含进去了。用户主要就是编写游戏等服务端的消息处理吧。 当是客户端时,TCP/UDP的端口可以对应到sockfd、进程号、或线程号。但如是服务端,就不一样了;虽然能对应到进程号,但可能有几百万个连接、sockfd文件号。所以,服务端应设置流标签(低24位) = sockfd文件号(连接号);这样、下次客户端的带有相同流标签(连接号)的请求到来时,服务端的底层就可迅速定位到相应的连接v节点(当然还需要比对一下)。一、服务端程序 APO的进程就是一个消息恒循环,用户代码入口main(); 就是执行用户编写的进程消息处理代码。我

8、们只需要在进程共用部分的初始化方法中Process_init(); 加入以服务端方式、TCP或UDP、最大连接数BACKLOG(单位为256个连接)、客户端发来的请求报文最大长度RECVLEN(单位行E)、服务端的发送流容器变量、的opens()方法。那么,余下的就是第二层TCP/UDP、用户CPU线路的系统网络服务进程的事情了。每当有一个新的属于服务进程的TCP/UDP数据报到来,第二层会给服务进程的动态优先级加码、以便服务进程可以更快的得到CPU;同时给服务进程发出一个消息(包含连接号sockfd、状态码等等)。当服务进程获得CPU时,可能已经有n个消息了;1、系统读入一个消息到H2行寄存

9、器,服务进程处理该消息;2、判断、如果是第二层的系统网络服务进程发出,那么是网络数据报消息,用sockfd.成员,提取数据报、分析是什么请求、处理该请求,最后回发一个服务器数据报。3、循环回到1,如果没有需处理的消息、服务进程让步挂起返回。至于是如何构建一个连接,有上千万个连接、数据报的内存分配、IP包组装等等;都不是应用层需关心的,那是底层的事情。所以,APO的服务端程序没料啊,就一个opens()和回发服务器数据报时、可能使用到的sendto()(该方法与LINUX、UINX、WINDOWS的有区别)、或关闭一个连接close()。那些、bind()、socket()、listen()、a

10、ccept()、connect()、write()、read()、recvfrom()、upds_respon()、recv()、send()、recvmsg()、sendmsg()、shutdoen()、sigio、select()等等、通通清除;还应用程序员一个干净的世界。要注意的是:如果同一个连接的客户端发了一个数据报,在服务进程还没处理完毕时,又发来一个数据报;客户端将受到流量抑制。如果前面的数据报达到1GB以上,客户端将立刻受到流量抑制、不允许再发数据报;直到服务进程处理完上一个数据报。至于、黑客回溯追踪,恶意TCP/UDP包判断,连接处理,重发等定时器,IP黑名单,攻击报警、包过滤

11、等等都是底层的事情,用户不必关注。我知道UDP、可能上千万个连接问题不大,但TCP就需另外对待了;就那几种定时器就不好处理,难道要设计几千万个定时器?这不可能;有待研究。二、客户端编程 用户可以在进程、或线程内设置客户端TCP/UDP程序。还是那3个方法,但opens方法的参数设置不一样;也不是在初始化方法出现;在线程、或进程打开一个连接opens,那通常是需要用户关闭连接close。 BUxE msg; / 在主程序、声明报文发送流容器(x行)。Thread_client() / 在线程内的客户端方法、线程入口。 sockfd = opens( FLAG.PORT );/ 获得socket文

12、件号, PORT = XX指定的客户端口,0由系统指定端口;/ FLAG = 0xA000(TCP)、0x8000(UDP);由第二层建立连接。/ 设置需连接的服务器端IP地址、端口等sockfd.vnode.MDA = ?; / 服务端的以太网目标地址sockfd.vnode.DLADD = ?;/ 服务端目标链路地址,DLADD + MD目标IP地址sockfd.vnode.DPORT = ?; / 服务端的目的端口 msg = ?; / 填写第一个消息报文。 sendto( sockfd, flags, msg, len ); / 发送第一个数据报。 PRET / 分支定点等待消息、阻塞

13、返回;新的线程入口在下一条指令。 msgpro(); / 服务器返回的数据报处理方法;消息在H2,线程新入口。/ 收到一个服务器数据报、由二层返回一个消息到相应进程,而进程将启动相/ 应的线程msgpro()方法来处理。 If FLAG.关闭标志 = 1 then goto tclt; msg = ?; / 填写消息报文。 sendto( sockfd, flags, msg, len ); / 由第二层发送一个新的请求数据报。 WRET / 等待消息、阻塞返回,准备处理下一个数据报消息。tclt: close(sockfd); / 关闭连接 TRET / 线程终止返回/ msg也可以是关联到

14、进程、或线程打开的一个普通文件号的流容器;这样,客户端也就可以上传一个文件(文件大小可到4GB);APO的数据报可以大到4GB。三、opens()、sendto()、close()方法 opens()方法只是把应用层的参数传入系统层(第二层),并返回一个文件号;客户端与服务端的参数是不一样的。对于返回的文件号sockfd,客户端才使用;而服务端是使用消息中的由第二层给出的新的连接文件号。R0参数FLAG.PORT:高16位R0H标志FLAG、低16位R0L TCP/UDP的指定端口PORT。APO的TCP服务端、oxE000,TCP客户端、oxA000;APO的UDP服务端、oxC000,UD

15、P客户端、ox8000。/ FLAG.15 DOMAIN; 协议域:1、INET_TYPE,0、其它。/ FLAG.14 NETMODEL; 网络模式:1、serve服务端,0、client客户端。/ FLAG.13 PROTOCOL; 协议:1、TCP(SOCK_STREAM),0、UDP(SOCK_DGRAM)。/ FLAG.12-8 STADE; 5位连接状态标志。/ FLAG.7-0 TYPE; 协议类型:/ PF_INET、IPAPO internet协议,PF_INET、IPV4 internet协议,/ PF_INET6、IPV6 internet协议,PF_IPX、NOVELL

16、协议,/ PF_NETLINK、内核用户界面协议,PF_X25、X.25/ISO-8208协议,/ PF_AX25、AMATEUR RADIO AX2.5协议,PF_ATMPVC、原始ATMPVC访问,/ PF_APPLETALK、APPLETALK协议,PF_PACKET、底层包访问协议, socket文件是在内存建立的、和其它类型的文件不一样,无须i节点、目录项,也不需要文件打开表项;只有不一样的v节点,描述了一个连接。4E大小的v节点,前面2E是发送IP数据包的包头(包括MAC头、IP头、TCP/UDP头);后2E是连接描述,TCP/UDP的连接参数;下一章会详细说明。1、服务端模式:s

17、ockfd = opens( FLAG.PORT, BACKLOG, RECVLEN );BU16 BACKLOG; / 最大连接数、单位为256个连接。R1LBU32 RECVLEN; / 低24位,允许的最大报文长度、单位E。R22、客户端模式:sockfd = opens( FLAG.PORT ); 需要使用返回的文件号来设置v节点中服务端的IP地址、端口号。sockfd.vnode.MDA = ?; / 服务端的以太网目标地址sockfd.vnode.DLADD = ?;/ 服务端的目标链路地址,DLADD + MDA目标IP地址sockfd.vnode.DPORT = ?; / 服务端的目的端口3、sendto()方法:数据报的接收是自动的,进程或线程只要根据第二层传来的消息做处理就行了;那么,要发送数据报就需使用sendto()方法了。APO中,不管TCP(强连接)、还是UDP(弱连接)都是通过连接来发送数据的,代表连接的是文件号sockfd、描述连接的是

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论