著录项信息
专利名称 | 一种TCP数据包的传输方法 |
申请号 | CN200810055730.6 | 申请日期 | 2008-01-08 |
法律状态 | 权利终止 | 申报国家 | 中国 |
公开/公告日 | 2008-07-09 | 公开/公告号 | CN101217493 |
优先权 | 暂无 | 优先权号 | 暂无 |
主分类号 | H04L12/56 | IPC分类号 | H;0;4;L;1;2;/;5;6;;;H;0;4;L;2;9;/;0;6查看分类表>
|
申请人 | 北京大学 | 申请人地址 | 北京市海淀区颐和园路5号
变更
专利地址、主体等相关变化,请及时变更,防止失效 |
权利人 | 北京大学 | 当前权利人 | 北京大学 |
发明人 | 张建宇;姚嘉;刘晓舟;廖唯棨;邹维 |
代理机构 | 北京君尚知识产权代理事务所(普通合伙) | 代理人 | 余长江 |
摘要
本发明的目的在于提供一种TCP数据包的传输方法,该方法通过将非本地TCP数据包直接重定向到本地网络协议栈进行处理(不依赖于网络地址转换技术)、流套接字负载均衡、减少内核层和用户层之间的数据拷贝传递、在内核层的流套接字之间直接传递TCP数据包以及减少网络协议栈中执行数据包构建等复杂操作的开销,提高了内核层内部各模块间传输和处理TCP数据包以及内核层与用户层业务程序之间传输数据的效率,实现了应用网关对TCP流量应用层数据的在线高速处理、TCP数据包的快速转发以及对大量并发TCP会话的支持,并保证了应用网关对于通信源端和目的端的透明性。
1.一种TCP数据包的传输方法,其步骤如下:
1)将应用网关接收到的、目的IP地址为非本地IP地址的TCP数据包传输到内核层的数据包转发模块,数据包转发模块将数据包内核数据结构的bsepsocket字段置1;
2)数据包转发模块根据负载均衡算法从用户层业务程序创建的“监听”流套接字池中选出一个“监听”流套接字,将其本地监听端口保存到数据包的内核数据结构中;
3)所述“监听”流套接字响应新建TCP连接握手请求,并创建“数据”流套接字,所述“监听”流套接字和“数据”流套接字包含三个数据包缓冲队列:接收队列、发送队列和深度处理队列;“监听”流套接字还包含一个监听队列和一个新建TCP连接队列;
4)数据包转发模块将TCP数据包重定向到内核层的本地网络协议栈;
5)本地网络协议栈的TCP输入处理模块对TCP数据包的TCP包头进行解析处理,在“数据”流套接字散列表中查找是否存在与数据包对应的“数据”流套接字;
6)若存在“数据”流套接字,则将数据包加入到“数据”流套接字的接收队列的队尾,并跳到步骤9;
7)若不存在“数据”流套接字,则在“监听”流套接字散列表中找到数据包转发模块选出的“监听”流套接字,将数据包加入到“监听”流套接字的监听队列的队尾;
8)TCP新建连接模块从监听队列队首取出TCP数据包,完成与客户机的新建TCP连接握手,创建与客户机进行通信的“数据”流套接字,将该流套接字加入到内核中的“数据”流套接字散列表以及“监听”流套接字的新建TCP连接队列队尾;
9)用户层的业务程序调用套接字的系统调用函数accept(),从“监听”流套接字的新建TCP连接队列队首取出“数据”流套接字并返回其信息给业务程序;调用套接字的系统调用函数socket(),创建与服务器通信的“数据”流套接字,调用套接字的系统调用函数setsockopt(),将其内核数据结构的sk_sepsocket字段置1;调用套接字的系统调用函数connect(),建立应用网关与服务器间的TCP连接;
10)业务程序调用套接字的系统调用函数,所述的系统调用函数为recv()、recvmsg()或recvfrom(),触发TCP输入处理模块从“数据”流套接字的接收队列的队首取出TCP数据包,还原提取出应用层数据并拷贝到业务程序提供的用户层缓冲区中,如果所述recv()、recvmsg()或recvfrom()函数的参数flags中包含标识MSG_PREINSPECTING,则将数据包加入到“数据”流套接字的深度处理队列队尾;
11)业务程序解析处理用户层缓冲区中的数据,调用套接字的系统调用函数,所述的系统调用函数为transfer()、send()、sendmsg()或sendto(),并根据所述transfer()、send()、sendmsg()或sendto()函数的参数flags中设置的不同标识,执行对“数据”流套接字深度处理队列中的原始TCP数据包的处理操作,包括:丢弃;对TCP数据包的内容不做任何修改原样发送出去;采用业务程序提供的数据替换TCP数据包的内容后发送出去;其中上述步骤中所有系统调用函数均兼容伯克利套接字。
2.如权利要求1所述的一种TCP数据包的传输方法,其特征在于步骤2)中所述的“监听”流套接字池的创建方法如下:
1)用户层的业务程序调用套接字的系统调用函数socket(),创建一个流套接字;
2)业务程序调用套接字的系统调用函数bind(),设置流套接字的本地监听端口;
3)业务程序调用套接字的系统调用函数listen(),将流套接字设置为“监听”流套接字,并以本地监听端口为键值将其加入内核中的“监听”流套接字散列表;
4)业务程序创建多个“监听”流套接字,形成一个“监听”流套接字池。
3.如权利要求1所述的一种TCP数据包的传输方法,其特征在于步骤2)中所述的负载均衡算法采用对源IP地址、源端口、目的IP地址和目的端口进行哈希的方法。
4.如权利要求1所述的一种TCP数据包的传输方法,其特征在于步骤5)中,TCP输入处理模块根据数据包的目的IP地址、目的端口、源IP地址和源端口信息查找是否存在对应的“数据”流套接字。
5.如权利要求1所述的一种TCP数据包的传输方法,其特征在于步骤7)中在TCP输入处理模块根据数据包内核数据结构中保存的“监听”流套接字的本地监听端口信息,找到数据包转发模块选出的“监听”流套接字。
6.如权利要求1所述的一种TCP数据包的传输方法,其特征在于步骤9)中所述信息包括目的IP地址、目的端口、源IP地址和源端口。
7.如权利要求1所述的一种TCP数据包的传输方法,其特征在于步骤11)所述的执行对“数据”流套接字深度处理队列中原始TCP数据包的丢弃操作的处理步骤为:用户层的业务程序调用套接字的系统调用函数send()、sendmsg()或sendto(),所述send()、sendmsg()或sendto()函数的参数flags置为MSG_POSTINSPECTING和MSG_DROP,将“数据”流套接字的深度处理队列中当前所有原始TCP数据包全部移出并丢弃。
8.如权利要求1所述的一种TCP数据包的传输方法,其特征在于步骤11)所述的执行对“数据”流套接字深度处理队列中原始TCP数据包内容的发送操作的处理步骤为:
1)用户层的业务程序调用套接字的系统调用函数transfer(),调用函数均兼容伯克利套接字;
2)transfer()将“数据”流套接字的深度处理队列中当前所有原始TCP数据包全部移出;
3)如果transfer()函数的参数flags中包含MSG_POSTINSPECTING标识,但不包含MSG_REPLACE标识,则将上述原始TCP数据包去掉TCP包头后加入要发送TCP数据包的流套接字dsocket的发送队列队尾,经本地网络协议栈和数据包转发模块执行完协议封装、TCP状态机维护、数据链路层或网络层转发信息查找这些处理工作后,将其发送出去;
4)如果flags中同时包含MSG_POSTINSPECTING标识和MSG_REPLACE标识,则将业务程序提供的应用层数据从用户层拷贝到内核层,然后复用上述原始TCP数据包,去掉其TCP包头并用应用层数据替换数据包的内容,如果数据的长度超过原始TCP数据包内容的总长度,则拷贝新的TCP数据包来放置超长部分的数据,将数据包加入要发送TCP数据包的流套接字dsocket的发送队列队尾,经本地网络协议栈和数据包转发模块发送出去。
一种TCP数据包的传输方法 \n技术领域\n[0001] 本发明属于计算机网络和数据通信技术领域,涉及一种TCP(Transmission ControlProtocol)数据包的传输方法,可用于应用网关的设备和软件中,以提高网关传输TCP数据包以及处理其应用层数据的效率,减少系统开销和网络延迟。 \n背景技术\n[0002] 应用网关通常采用透明代理技术,在客户机和服务器之间充当中间人的角色,接收流经的TCP数据包并重定向到内核层的本地网络协议栈中,由协议栈对数据包进行协议解析处理和TCP流重组,还原提取出应用层数据,然后通过流套接字(Stream Socket)将应用层数据从内核层拷贝到用户层,传送给用户层的业务程序(如病毒检测程序、关键词过滤程序等)进行各种处理和修改(如删除、替换);用户层业务程序将处理修改后的数据再通过流套接字从用户层拷贝到内核层,交给本地网络协议栈,并通知协议栈采用重定向前原始数据包的目的IP地址和目的端口来重新构建数据包并进行协议封装,然后发送出去。\n其中,流量重定向多采用网络地址转换技术(Network Address Translation,简称NAT),这主要是由于传统的套接字实现(如伯克利套接字,参见文献:W.R.Stevens,B.Fenner andA.M.Rodoff,“UNIX Network Programming,Volume 1:The Sockets Networking API”,Addison Wesley,2003;IEEE Std 1003.1)和网络协议栈的实现不能接收和处理非本地目的IP地址和目的端口的数据包,也不能发送非本地源IP地址和源端口的数据包。因此,应用网关对接收到的数据包要进行目的地址转换(DNAT),将其目的IP地址和目的端口改为网关的本地IP地址和本地端口,从而将其重定向到应用网关的本地网络协议栈中;对于待发送的数据包则要进行源地址转换(SNAT),将其源IP地址和源端口从网关的本地IP地址和本地端口改为DNAT前原始数据包的源IP地址和源端口。为了区分属于不同TCP连接的数据包,需要对TCP流量进行连接跟踪并在连接表中记录NAT操作前后的IP地址和端口信息。 \n[0003] 上述技术存在如下几个主要缺陷,造成应用网关处理效率和容量的大幅下降,无法满足在高流量带宽以及存在大量并发会话的网络环境中的性能需求:(1)NAT技术对每一个数据包的IP地址和端口字段进行修改并需重新计算校验和,对系统性能造成一定影响; (2)NAT技术依赖于连接跟踪,需要建立会话表,为每一个TCP会话保存IP地址、端口等信息,而会话跟踪和会话表管理任务的时空间开销繁重,会严重影响系统的性能;(3)为了保持NAT转换前后TCP连接的一一对应关系,在执行DNAT操作时需要将不同的TCP连接的数据包目的端口转换为不同的本地端口,因而系统能够支持的最大并发连接数受限于可用的本地端口数目(不多于65535个);(4)数据在内核层和用户层之间多次拷贝传递,以及在发送数据时需要重新进行数据包构建等操作,也会严重降低系统性能。 发明内容\n[0004] 本发明的目的在于提供一种TCP数据包传输方法,通过将非本地TCP数据包直接重定向到本地网络协议栈进行处理(不依赖于网络地址转换技术)、流套接字负载均衡、减少内核层和用户层之间的数据拷贝传递、在内核层的流套接字之间直接传递TCP数据包以及减少网络协议栈中执行数据包构建等复杂操作的开销,提高了内核层内部各模块间传输和处理TCP数据包以及内核层与用户层业务程序之间传输数据的效率。 \n[0005] 本发明的上述发明目的是通过如下的技术方案实现:一种TCP数据包的传输方法,其步骤如下: \n[0006] 1.将应用网关接收到的、目的IP地址为非本地IP地址的TCP数据包传输到内核层的数据包转发模块,数据包转发模块将数据包内核数据结构的bsepsocke字段置1; [0007] 2.数据包转发模块根据负载均衡算法从用户层业务程序创建的“监听”流套接字池中选出一个“监听”流套接字,将其本地监听端口保存到数据包的内核数据结构中; [0008] 3.所述“监听”流套接字响应新建TCP连接握手请求,并创建“数据”流套接字,所述“监听”流套接字和“数据”流套接字包含三个数据包缓冲队列:接收队列、发送队列和深度处理队列;“监听”流套接字还包含一个监听队列和一个新建TCP连接队列; [0009] 4.数据包转发模块将TCP数据包重定向到内核层的本地网络协议栈; [0010] 5.本地网络协议栈的TCP输入处理模块对TCP数据包的TCP包头进行解析处理,在“数据”流套接字散列表中查找是否存在与数据包对应的“数据”流套接字; [0011] 6.若存在“数据”流套接字,则将数据包加入到“数据”流套接字的接收队列的队尾,跳到步骤9; \n[0012] 7.若不存在“数据”流套接字,则在“监听”流套接字散列表中找到数据包转发模块选出的“监听”流套接字,将数据包加入到“监听”流套接字的监听队列的队尾; [0013] 8.TCP新建连接模块从监听队列队首取出TCP数据包,完成与客户机的新建TCP连接握手,创建与客户机进行通信的“数据”流套接字,将该流套接字加入到内核中的“数据”流套接字散列表以及“监听”流套接字的新建TCP连接队列队尾; \n[0014] 9.用户层的业务程序调用套接字的系统调用函数accept(),从“监听”流套接字的新建TCP连接队列队首取出“数据”流套接字并返回其信息给业务程序;调用套接字的系统调用函数socket(),创建与服务器通信的“数据”流套接字,调用套接字的系统调用函数setsockopt(),将其内核数据结构的sk_sepsocket字段置1;调用套接字的系统调用函数connect(),建立应用网关与服务器间的TCP连接; \n[0015] 10.业务程序调用套接字的系统调用函数,所述的系统调用函数为recv()、recvmsg()或recvfrom(),触发TCP输入处理模块从“数据”流套接字的接收队列的队首取出TCP数据包,还原提取出应用层数据并拷贝到业务程序提供的用户层缓冲区中,如果所述recv()、recvmsg()或recvfrom()函数的参数flags中包含标识MSG_PREINSPECTING,则将数据包加入到“数据”流套接字的深度处理队列队尾; \n[0016] 11.业务程序解析处理用户层缓冲区中的数据,调用套接字的系统调用函数,所述的系统调用函数为transfer()、send()、sendmsg()或sendto(),并根据所述transfer()、send()、sendmsg()或sendto()函数的参数flags中设置的不同标识,执行对“数据”流套接字深度处理队列中的原始TCP数据包的处理操作,包括:丢弃;对TCP数据包的内容不做任何修改原样发送出去;采用业务程序提供的数据替换TCP数据包的内容后发送出去;其中上述步骤中所有系统调用函数均兼容伯克利套接字。 \n[0017] 进一步,步骤2中所述的用户层的业务程序创建“监听”流套接字池的步骤为: [0018] 1)用户层的业务程序调用套接字的系统调用函数socket(),创建一个流套接字; [0019] 2)业务程序调用套接字的系统调用函数bind(),设置流套接字的本地监听端口; [0020] 3)业务程序调用套接字的系统调用函数listen(),将流套接字设置为“监听”流套接字,并以本地监听端口为键值将其加入内核中的“监听”流套接字散列表; [0021] 4)业务程序创建多个“监听”流套接字,形成一个“监听”流套接字池。 [0022] 上述步骤2中,负载均衡算法采用对源IP地址、源端口、目的IP地址和目的端口进行哈希的方法。 \n[0023] 上述步骤5中,TCP输入处理模块根据数据包的目的IP地址、目的端口、源IP地址和源端口信息查找是否存在对应的“数据”流套接字。 \n[0024] 上述步骤7中,TCP输入处理模块根据数据包内核数据结构中保存的“监听”流套接 字的本地监听端口信息,找到数据包转发模块选出的“监听”流套接字。 [0025] 上述步骤9中所述信息包括客户机的IP地址和端口、服务器的IP地址和端口。 [0026] 上述步骤10中,所述的系统调用函数为recv()、recvmsg()或recvfrom()。 [0027] 进一步,上述步骤11中所述的执行对“数据”流套接字深度处理队列中原始TCP数据包的丢弃操作的处理步骤为:用户层的业务程序调用套接字的系统调用函数send()、sendmsg()或sendto(),函数参数flags置为MSG_POSTINSPECTING和MSG_DROP,将流套接字的深度处理队列中当前所有原始TCP数据包全部移出并丢弃;所述函数均兼容伯克利套接字。 \n[0028] 进一步,上述步骤11中所述的执行对“数据”流套接字深度处理队列中原始TCP数据包内容的发送操作的处理步骤为: \n[0029] 1)用户层的业务程序调用套接字的系统调用函数transfer(),其函数定义如下: [0030] int transfer(int ssocket,int dsocket,void*buf,int len,int flags); [0031] 其中,参数ssocket为原始TCP数据包所在的套接字,dsocket为要发送TCP数据包的套接字,buf为业务程序提供的应用层数据缓冲区指针,len为数据缓冲区中数据的字节数,flags为标识字段。transfer()的返回值为实际上成功发送出去的应用层数据的字节数; \n[0032] 2)transfer()将流套接字ssocket的深度处理队列中当前所有原始TCP数据包全部移出; \n[0033] 3)如果函数参数flags中包含MSG_POSTINSPECTING标识但不包含MSG_REPLACE标识,则将上述原始TCP数据包去掉TCP包头后加入流套接字dsocket的发送队列队尾,等待经本地网络协议栈(包括TCP输出处理模块)和数据包转发模块执行完协议封装、TCP状态机维护、数据链路层或网络层转发信息查找这些处理工作后,将其发送出去; [0034] 4)如果flags中包含MSG_POSTINSPECTING标识和MSG_REPLACE标识,则将业务程序提供的应用层数据从用户层拷贝到内核层,然后复用上述原始TCP数据包,去掉其TCP包头并用上述应用层数据替换数据包的内容——如果数据的长度超过这些原始TCP数据包内容的总长度,则拷贝新的TCP数据包来放置超长部分的数据——然后将数据包加入流套接字dsocket的发送队列队尾,等待经本地网络协议栈和数据包转发模块发送出去。 [0035] 本发明的优点和积极效果如下: \n[0036] 1.本发明通过将非本地TCP数据包直接重定向到本地网络协议栈进行处理,以及通过在内核的流套接字间直接传递TCP数据包,提高了内核层内部各模块间传输和处理TCP数据包的效率; \n[0037] 2.本发明通过设置套接字的数据包缓冲深度处理队列,以及根据系统调用参数flags中设置的不同标识对其中的原始TCP数据包执行处理,减少了在内核层和用户层之间多次拷贝传递数据以及在网络协议栈中执行数据包构建等复杂操作的开销; [0038] 3.本发明通过上述技术手段以及数据报套接字负载均衡,实现了应用网关对TCP流量应用层数据的在线高速处理、TCP数据包的快速转发以及对大量并发TCP连接的支持。 [0039] 4.本发明保证了应用网关对于通信源端和目的端的透明性。 \n附图说明\n[0040] 图1本发明实施例的系统结构图; \n[0041] 图2本发明实施例的创建“监听”流套接字的流程图; \n[0042] 图3本发明实施例的处理TCP数据包的流程图。 \n具体实施方式\n[0043] 以防病毒应用安全网关为例,参照附图对本发明的一种面向应用网关的TCP协议处理与流套接字实现方法进行详细说明。 \n[0044] 图1为该实施例的系统结构图。 \n[0045] TCP数据包的内核数据结构包含一个非本地数据包标识字段bsepsocket,应用网关的本地网络协议栈根据该字段是否置1来区分非本地数据包(即目的IP地址和源IP地址均不为本地IP地址的数据包)和本地数据包。 \n[0046] 数据包的内核数据结构包含一个该数据包所属套接字的本地监听端口字段sepsocket_listen_port,通过设置该字段,将新建TCP连接握手阶段的数据包分配给业务程序创建的“监听”流套接字进行处理,并实现不同“监听”流套接字间的负载均衡。“监听”流套接字负责响应处理新建TCP连接握手请求并创建对应的“数据”流套接字,由“数据”流套接字负责在TCP连接建立后响应处理该连接后续的TCP数据包。 \n[0047] 本地网络协议栈中包含两个流套接字散列表:一个是“监听”流套接字散列表,用以保存所有通过套接字的系统调用socket()和listen()进行创建和设置的“监听”流套接字;另一个是“数据”流套接字散列表,用以保存所有由“监听”流套接字创建的“数据”流套接字。通过这两个散列表实现对流套接字的快速查找。 \n[0048] 套接字的内核数据结构包含一个标识字段sk_sepsocket,当该字段置1时允许流套接 字处理非本地TCP数据包。同时为该标识字段增加一个对应的SOL_SOCKET级别的套接字选项SO_SEPSOCKET,使得业务程序可以通过套接字的系统调用setsockopt()对该标识字段进行设置。 \n[0049] 套接字的内核数据结构包含如下四个字段:源IP地址、源端口、目的IP地址、目的端口,用于保存通信双方的IP地址和端口信息。 \n[0050] 每个流套接字包含三个数据包缓冲队列:接收队列sk_receive_queue、发送队列sk_write_queue和深度处理队列sk_inspect_queue,用于分别保存从本地网络协议栈接收到的数据包、准备通过本地网络协议栈发送的数据包以及正在由业务程序进行处理的数据包。 \n[0051] 每个“监听”流套接字还包含一个数据包缓冲队列:监听队列prequeue,用于保存“监听”流套接字接收到的数据包。 \n[0052] 每个“监听”流套接字包含一个新建TCP连接队列accept_queue,保存由该“监听”流套接字完成TCP握手的新建TCP连接的信息。 \n[0053] 如图2所示,创建“监听”流套接字的流程为: \n[0054] (1)用户层的业务程序调用套接字的系统调用函数socket(),创建一个流套接字。socket()与伯克利套接字兼容,其调用形式如下: \n[0055] int socketfd=socket(PF_INET,SOCK_STREAM,IPPROTO_IP); [0056] (2)业务程序调用套接字的系统调用函数setsockopt(),将该流套接字的sk_sepsocket字段置1,从而允许该流套接字处理非本地TCP数据包。setsockopt()与伯克利套接字兼容,其调用形式如下: \n[0057] setsockopt(socketfd,SOL_SOCKET,SO_SEPSOCKET,1,sizeof(int)); [0058] (3)业务程序调用套接字的系统调用函数bind()——与伯克利套接字兼容,设置该流套接字的本地监听端口; \n[0059] (4)业务程序调用套接字的系统调用函数listen()——与伯克利套接字兼容,将该流套接字设置为“监听”流套接字,并将其加入“监听”流套接字散列表。 [0060] 此外,业务程序通常创建多个“监听”流套接字,形成一个“监听”流套接字池,再通过并行和负载均衡将TCP新建连接的请求分散到不同的“监听”流套接字进行处理,以提高TCP连接的新建速率。 \n[0061] 如图3所示,防病毒应用安全网关处理TCP数据包的流程为: \n[0062] (1)对于防病毒应用安全网关接收到的、目的IP地址为非本地IP地址的TCP数据包,送入内核层的数据包转发模块进行处理,根据一定的规则判断数据包是否需要由用户层业务程序进行处理; \n[0063] (2)如果不需要,则将数据包直接转发出去,结束; \n[0064] (3)如果需要,则数据包转发模块将数据包内核数据结构的bsepsocket字段置1,标明其为非本地数据包; \n[0065] (4)数据包转发模块根据负载均衡算法(参见文献:C.Kopparapu,“Load BalancingServers,Firewalls,and Caches”,Wiley,2002)从业务程序创建的“监听”流套接字池中选出一个“监听”流套接字,将该套接字的本地监听端口保存到数据包内核数据结构的sepsocket_listen_port字段中。为了保证一个确定的TCP连接对应到一个确定的“监听”流套接字,TCP负载均衡算法可采用对源IP地址、源端口、目的IP地址和目的端口进行哈希(Hash)的方法,如:假设“监听”流套接字池中有n个套接字,则当一个TCP的syn包到来时,计算其源端口、目标端口、源IP地址的低16位和目的IP地址的低16位之和,然后除以n取余,得到余数m,从而将该TCP syn包分配给编号为m的“监听”流套接字; [0066] (5)数据包转发模块将TCP数据包直接重定向到内核层的本地网络协议栈; [0067] (6)本地网络协议栈的TCP输入处理模块得到bsepsocket字段置1的TCP数据包后,对数据包的TCP包头进行解析处理; \n[0068] (7)TCP输入处理模块在“数据”流套接字散列表中查找是否存在sk_sepsocket字段置1且目的IP地址、目的端口、源IP地址和源端口与数据包的对应字段信息一致的套接字; \n[0069] 如果存在,则将TCP数据包加入该“数据”流套接字的sk_receive_queue队尾,等待用户层业务程序对其应用层数据进行防病毒检测过滤; \n[0070] 如果不存在,则在“监听”流套接字散列表中查找sk_sepsocket字段置1且本地监听端口与数据包内核数据结构的sepsocket_listen_port字段相同的“监听”流套接字。\n如果找到,则将数据包加入该“监听”流套接字的prequeue队尾;否则丢弃该TCP数据包,结束; \n[0071] TCP新建连接模块从“监听”流套接字的prequeue队首取出一个TCP数据包,检查TCP包头中的syn、ack和rst字段。若TCP包头的syn字段为1,ack字段和rst字段为0,则该数据包是TCP syn包;若TCP包头的ack字段为1,syn字段和rst字段为0,则该数 据包是TCP ack包;若TCP包头的ack字段为1,syn字段、rst字段和fin字段为0,则该数据包是TCP syn-ack包。对于TCP syn包,TCP新建连接模块用该数据包的目的IP地址、源IP地址为源IP地址和目的IP地址构建构建一个TCP syn-ack包发送给客户机。对于TCPack包,TCP新建连接模块创建一个与客户机进行通信的“数据”流套接字,将该流套接字内核数据结构的sk_sepsocket字段置1,然后将数据包的源IP地址、源端口(即客户机的IP地址和端口)和目的IP地址、目的端口(即服务器的IP地址和端口)信息分别填入该流套接字内核数据结构的目的IP地址、目的端口、源IP地址和源端口字段中。然后,将该流套接字加入到内核中的“数据”流套接字散列表以及“监听”流套接字的accept_queue队尾; \n[0072] (8)用户层的业务程序调用套接字的系统调用函数accept()——与伯克利套接字兼容,调用形式如下: \n[0073] int csockfd=accept(socketfd,addr,addrlen); \n[0074] 其中参数socketfd为“监听”流套接字。accept()从socketfd的accept_queue队首取出一个“数据”流套接字,将其内核数据结构中的源IP地址、源端口(即服务器的IP地址和端口)和目的IP地址、目的端口(即客户机的IP地址和端口)字段等信息通过参数addr返回给业务程序; \n[0075] (9)业务程序调用套接字的系统调用函数socket(),创建一个与服务器通信的“数据”流套接字,并调用套接字的系统调用函数setsockopt()将其内核数据结构的sk_sepsocket字段置1,从而允许其处理非本地TCP数据包; \n[0076] (10)业务程序调用套接字的系统调用函数connect()——与伯克利套接字兼容,与服务器建立TCP连接。调用的形式如下: \n[0077] connect(ssockfd,addr,addrlen); \n[0078] 其中,参数addr中包含客户机的IP地址和端口、服务器的IP地址和端口。\nconnect()将套接字内核数据结构中的源IP地址、源端口、目的IP地址和目的端口字段分别置为客户机IP地址和端口、服务器IP地址和端口,触发TCP新建连接模块向服务器发起新建TCP连接请求并完成TCP连接握手过程; \n[0079] (11)业务程序调用套接字的系统调用函数recv()、recvmsg()或recvfrom()——与伯克利套接字兼容,调用形式如下: \n[0080] int i=recv(socketfd,buf,len,MSG_PREINSPECTING); \n[0081] inti=recvmsg(socketfd,msg,MSG_PREINSPECTING); \n[0082] int i = recvfrom(socketfd,buf,len,MSG_PREINSPECTING,sockaddr,addrlen); \n[0083] 其中,函数参数flags置为MSG_PREINSPECTING。recv()、recvmsg()和recvfrom()触发TCP输入处理模块从“数据”流套接字socketfd的sk_receive_queue队首取出TCP数据包进行流重组,将应用层数据还原提取出来后拷贝到业务程序提供的用户层缓冲区buf或msg中。执行完上述操作后,由于函数参数flags中包含MSG_PREINSPECTING标识,则不释放TCP数据包,而是将其加入到流套接字的sk_inspect_queue队尾,等待业务程序的处理结果; \n[0084] (12)业务程序对buf或msg中的数据进行应用协议解析,提取出其中的数据进行病毒扫描检测,并针对不同的检测结果执行相应的处理,包括如下几种情况:通过检查,数据中不含病毒,原始TCP数据包的净荷不做修改、直接转发出去;未通过检查,数据中含有病毒,将原始TCP数据包丢弃;未通过检查,数据中含有病毒,将原始TCP数据包的净荷进行替换后发送出去; \n[0085] (13)如果需要丢弃TCP数据包,则用户层的业务程序调用套接字的系统调用函数send()、sendmsg()或sendto()——与伯克利套接字兼容,将流套接字的sk_inspect_queue队列中当前所有原始TCP数据包全部移出并丢弃。调用形式如下: \n[0086] int i=send(socketfd,buf,len,MSG_POSTINSPECTING|MSG_DROP); [0087] int i=sendmsg(socketfd,msg,MSG_POSTINSPECTING|MSG_DROP); [0088] int i=sendto(socketfd,buf,len,MSG_POSTINSPECTING|MSG_DROP,sockaddr,addr_len); \n[0089] 其中,函数参数flags置为MSG_POSTINSPECTING和MSG_DROP的组合; [0090] (14)如果需要转发TCP数据包,则用户层的业务程序调用套接字的系统调用函数transfer()执行对流套接字深度处理队列中原始TCP数据包的处理,即在与客户机通信的“数据”流套接字和与服务器通信的“数据”流套接字之间传递并发送TCP数据包。\ntransfer()的定义如下: \n[0091] int transfer(int ssocket,int dsocket,void*buf,int len,int flags); [0092] 其中,参数ssocket为原始TCP数据包所在的套接字,dsocket为要发送TCP数据包的套接字,buf为数据缓冲区指针,len为数据缓冲区中数据的字节数,flags为标识字段。transfer()的返回值为实际上成功发送出去的应用层数据的字节数。 [0093] transfer()执行如下操作:1)将流套接字ssocket的sk_inspect_queue队列中当前所有原始TCP数据包全部移出;2)如果flags中包含MSG_POSTINSPECTING标识但不包含MSG_REPLACE标识,则将上述原始TCP数据包去掉TCP包头后加入流套接字dsocket的 sk_write_queue队尾,等待经本地网络协议栈(包括TCP输出处理模块)和数据包转发模块执行完协议封装、TCP状态机维护、数据链路层或网络层转发信息查找等处理工作后,将其发送出去;3)如果flags中包含MSG_POSTINSPECTING标识和MSG_REPLACE标识,则将buf或msg所指向的应用层数据从用户层拷贝到内核层,然后复用上述原始TCP数据包,去掉其TCP包头并用上述应用层数据替换数据包的内容。如果数据的长度超过这些原始TCP数据包内容的总长度,则拷贝新的TCP数据包来放置超长部分的数据。最后,将这些TCP数据包内核数据结构的bsepsocket字段置1,然后将其加入流套接字dsocket的sk_write_queue队尾,等待经本地网络协议栈和数据包转发模块发送出去。 \n[0094] 最后应说明的是:以上实施例仅用以说明而非限制本发明的技术方案,尽管参照上述实施例对本发明进行了详细说明,本领域的技术人员应当理解:依然可以对本发明进行修改或者等同替换,而不脱离本发明的精神和范围的任何修改或局部替换,其均应涵盖在本发明的权利要求范围当中。
法律信息
- 2016-03-02
未缴年费专利权终止
IPC(主分类): H04L 12/56
专利号: ZL 200810055730.6
申请日: 2008.01.08
授权公告日: 2011.05.04
- 2011-05-04
- 2008-09-03
- 2008-07-09
引用专利(该专利引用了哪些专利)
序号 | 公开(公告)号 | 公开(公告)日 | 申请日 | 专利名称 | 申请人 |
1
| |
2004-07-14
|
2002-12-31
| | |
2
| |
2007-06-20
|
2006-11-15
| | |
3
| |
2005-04-06
|
2004-10-29
| | |
被引用专利(该专利被哪些专利引用)
序号 | 公开(公告)号 | 公开(公告)日 | 申请日 | 专利名称 | 申请人 | 该专利没有被任何外部专利所引用! |