加入收藏 | 设为首页 | 会员中心 | 我要投稿 西安站长网 (https://www.029zz.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

不可不知的Socket和TCP连接过程

发布时间:2019-08-28 06:05:28 所属栏目:教程 来源:工控自动化专家
导读:副标题#e# 本文主要说明的是TCP连接过程中,各个阶段对套接字的操作,希望能对没有网络编程基础的人理解套接字是什么、扮演的角色有所帮助。如发现错误,敬请指出。 一. 背景 1.完整的套接字格式{protocol,src_addr,src_port,dest_addr,dest_port}。 这常被

此外,如果监听者发送SYN+ACK后,迟迟收不到客户端返回的ACK消息,监听者将被select()/poll()设置的超时时间唤醒,并对该客户端重新发送SYN+ACK消息,防止这个消息遗失在茫茫网络中。但是,这一重发就出问题了,如果客户端调用connect()时伪造源地址,那么监听者回复的SYN+ACK消息是一定到不了对方的主机的,也就是说,监听者会迟迟收不到ACK消息,于是重新发送SYN+ACK。但无论是监听者因为select()/poll()设置的超时时间一次次地被唤醒,还是一次次地将数据拷入send buffer,这期间都是需要CPU参与的,而且send buffer中的SYN+ACK还要再拷入网卡(这次是DMA拷贝,不需要CPU)。如果,这个客户端是个攻击者,源源不断地发送了数以千、万计的SYN,监听者几乎直接就崩溃了,网卡也会被阻塞的很严重。这就是所谓的syn flood攻击。

解决syn flood的方法有多种,例如,缩小listen()维护的两个队列的最大长度,减少重发syn+ack的次数,增大重发的时间间隔,减少收到ack的等待超时时间,使用syncookie等,但直接修改tcp选项的任何一种方法都不能很好兼顾性能和效率。所以在连接到达监听者线程之前对数据包进行过滤是极其重要的手段。

2.4 accept()函数

accpet()函数的作用是读取已完成连接队列中的第一项(读完就从队列中移除),并对此项生成一个用于后续连接的套接字描述符,假设使用connfd来表示。有了新的连接套接字,工作进程/线程(称其为工作者)就可以通过这个连接套接字和客户端进行数据传输,而前文所说的监听套接字(sockfd)则仍然被监听者监听。

例如,prefork模式的httpd,每个子进程既是监听者,又是工作者,每个客户端发起连接请求时,子进程在监听时将它接收进来,并释放对监听套接字的监听,使得其他子进程可以去监听这个套接字。多个来回后,终于是通过accpet()函数生成了新的连接套接字,于是这个子进程就可以通过这个套接字专心地和客户端建立交互,当然,中途可能会因为各种io等待而多次被阻塞或睡眠。这种效率真的很低,仅仅考虑从子进程收到SYN消息开始到最后生成新的连接套接字这几个阶段,这个子进程一次又一次地被阻塞。当然,可以将监听套接字设置为非阻塞IO模式,只是即使是非阻塞模式,它也要不断地去检查状态。

再考虑worker/event处理模式,每个子进程中都使用了一个专门的监听线程和N个工作线程。监听线程专门负责监听并建立新的连接套接字描述符,放入apache的套接字队列中。这样监听者和工作者就分开了,在监听的过程中,工作者可以仍然可以自由地工作。如果只从监听这一个角度来说,worker/event模式比prefork模式性能高的不是一点半点。

(编辑:西安站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读