listen()和accept()
作用:监听端口,TCP连接中的服务器端角色
调用格式:int listen(int sockfd, int backlog);
第一个参数:创建的sockfd,
好好理解第二个参数:未决连接,监听套接字队列。最开始是:已完成和未完成之和最大值。现在是:制定给定套接字上内核为之排队的最大已完成连接数。
对于一个调用listen()函数进行监听的套接字,操作系统回个这个套接字维护两个队列。
a、未完成连接的队列(SYN_RCVD):
当客户端发送TCP连接三次握手的第一次给服务器的时候,
服务器就会在未完成队列中创建一个跟这个syn包对应的一项。
可以看成是半连接,这个连接的状态从listen变成syn_rcvd状态,
同时返回给客户端返回第二次握手。
这个时候服务器在等待完成第三次握手
b、已完成连接的队列(ESTABLISHED)
当第三次握手完成了,这个连接就变成了ESTABLISHED状态。
每个已经完成三次握手的客户端都放在这个队列中作为一项。
1.1 监听套接字的队列
connect函数收到第二次握手包的时候返回。
RTT是未完成队列中的任意一项在未完成队列中留存的时间。
长短取决于客户端和服务器端的往返时间。第二次和第三次握手时间之和。
对于客户端就是在connect调用到返回的耗费时间。前两次握手时间之和。
三次握手的时间之和一般大致是187ms。这个时间很慢。
所以建立TCP连接的成本很高。各个客户端并行的建立连接。
1.2 accept()函数
就是用来从已完成连接队列中的队首位置取出来一项【每一项都是一个已经完成三路连接的TCP连接】,返回给进程。
如果已完成连接队列是空的,阻塞的accept()会一直卡在这里等待。一直到已完成队列中有一项是才会被唤醒。非阻塞的例外。
所以从编程角度,我们要尽快的用accept把已完成队列中的数据【TCP连接套接字】取走。这样已完成连接队列就不会满。
所以服务器程序,必须严格区分两个套接字。
一,监听套接字一直存在。
二,当客户端连接进来,操作系统会为每个成功建立三次握手的客户端创建一个套接字。accept返回的就是这种套接字。
也就是从已完成连接队列中取得的一项,服务器用这个套接字和客户端进行通信。
1.3 syn攻击
如果一个恶意客户迟迟不发送三次握手的第三个包。连接建立不起来,
那么处于DYN_RCVD这一项就会一直停留在未完成队列中,
停留时间大约是75秒,才会被操作系统干掉。
syn flood:典型的利用TCP/IP协议涉及弱点进行攻击的行为。服务器拒绝服务(DOS/DDOS(分布式))
,恶意用户通过伪造syn包的ip地址和端口号向服务器不断发送连接请求,而服务器返回的ACK包不会被真实的ip和端口进行回应,
造成未完成连接数增加知道达到了listen第二个设置的最大值,此时服务器开始忽略新进来了syn连接请求,同时拒绝为真实用户提供服务。
阻塞和非阻塞主要是指调用一个系统函数时,这个函数是否会导致进程进入sleep状态而言的。
阻塞I/O,调用函数卡在那里,等待事件发生,事件发生,函数返回。
accept()可以阻塞也可以不阻塞,根据listenfd决定
效率很低,一般不会用阻塞方式写服务器程序。
非阻塞I/O,调用函数吧listenfd设置成非阻塞的话,accept函数会立即返回,通过错误码判断accept返回的原因。不会卡主,充分利用时间片,执行效率更高。
鲜明特点,1)不断地调用accept,recvfrom函数来检查有没有数据到来,
函数会返回一个特殊的标识来告诉你,
EWULDBLOCK,EAGAIN,如果数据没到来,
有机会执行其他函数,但是也要不停的再次调用检查数据是否到来。
2)如果数据到来,
那么就得卡住把数据从内核缓冲区复制到用户缓冲区,
复制这个过程是卡住的。
3、同步与异步I/O
容易和阻塞非阻塞混淆:
异步I/O:调用函数立刻返回,之后不需要再次调用,指定接受缓冲区,
等服务端处理好了调用指定的回调函数。操作系统会判断是否到来,
如果数据到来了,操作系统会把数据拷贝到你所提供的缓冲区里,
然后调用你所制定的回调函数来通知你。整个过程中没有被卡住的地方。
同步I/O:select,poll,epoll。第一、先判断有没有数据,
有数据select返回,recvfrom取数据。当然取数据也会卡。
没数据继续卡。
要调用两个函数才能取到数据,但是做到了【I/O复用】
阻塞和非阻塞也归结为同步I/O;
3.1 I/O复用
所谓I/O复用,就是多个socket可以集合在一起,
可以用select这种同步I/O在这里等数据,多条TCP连接上任意一条有数据来,
哪条TCP有数据来,我们在用recvfrom去收。
所以这种调用一个函数可以判断一堆TCP连接是否来数据的能力,
叫做I/O多路复用。
3.2 思考题
1、如果已完成队列和未完成队列之后达到了listen函数的第二个参数。此时再有一个客户发送SYN连接,服务器怎么反应?
实际上服务器会忽略这个SYN包,过一会客户端会自动再次发送SYN包,因为服务器长时间没有回应。
2、三次握手完成了,连接被扔到已完成连接队列到调用accept函数把已完成连接队列取走的时间差过程中,客户端如果发送来数据,这个数据就会被保存在已经连接套接字的接收缓冲区里,这个接收缓冲区有多大,最大就能接收多少数据量。
转:https://www.jianshu.com/p/32fb2f35baf5
listen()和accept()的更多相关文章
- 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
[Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...
- Linux进程间通信(八):流套接字 socket()、bind()、listen()、accept()、connect()、read()、write()、close()
前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket进行通信的进程可以是同一台计算机的进程,也是可以是通过网络连接起来的不同计算机上的进程.通常我们使用socket进行网络编 ...
- listen和accept函数
listen函数是用来设置监听连接的句柄和队列 当listen函数执行完成以后,服务端就已经可以接受客户端来的新连接了,新连接完成以后listen会把客户端的ip,port和连接句柄放在监听队列里面, ...
- 【Linux 网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数:对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...
- 【转载】socket 的 connect、listen、accept 和全连接队列、半连接队列的原理
转自:http://blog.csdn.net/tennysonsky/article/details/45621341 写在前面: 1. accept 只是从全连接队列拿出一个已经建立好的socke ...
- tcp通讯中socket套接字accept和listen的关系
今天看到一个文章,客户端的connect在服务端调用accept之前,突然想到这可以建立正常的连接么?以前从没细细的思考过listen accept connect之前的关系,带着疑问学习了一下,记录 ...
- listen()
创建一个套接口并监听申请的连接. #include <winsock.h> int PASCAL FAR listen( SOCKET s, int backlog); S:用于标识一个已 ...
- socket listen backlog
http://stackoverflow.com/questions/4253454/question-about-listening-and-backlog-for-sockets The list ...
- 从Linux源码看Socket(TCP)的listen及连接队列
从Linux源码看Socket(TCP)的listen及连接队列 前言 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 今天笔者就来从Linux源码的角度看 ...
随机推荐
- git pull 拉取报错:fatal: refusing to merge unrelated histories
fatal: refusing to merge unrelated histories(拒绝合并不相关的历史) 使用 git pull origin master --allow-unrelated ...
- Maven配置使用阿里云镜像
在settings.xml文件中的mirrors下添加mirror标签 <!-- 阿里云仓库 --> <mirror> <id>alimaven</id> ...
- 【LeetCode】990. Satisfiability of Equality Equations 解题报告(C++ & python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS 并查集 日期 题目地址:https://le ...
- 【LeetCode】393. UTF-8 Validation 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/utf-8-va ...
- 【LeetCode】733. Flood Fill 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:DFS 方法二:BFS 日期 题目地址:ht ...
- [LeetCode]621. Task Scheduler 任务安排 题解
题目描述 给定一个char数组,代表CPU需要做的任务,包含A-Z,不用考虑顺序,每个任务能在1个单位完成.但是有规定一个非负整数n代表两个相同任务之间需要至少n个时间单位.球最少数量的时间单位完成所 ...
- Another kind of Fibonacci(hdu3306)
Another kind of Fibonacci Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- FAT
目录 概 主要内容 代码 Zhang J., Xu X., Han B., Niu G., Cui L., Sugiyama M., Kankanhalli M. Attacks which do n ...
- Kafka基础教程(二):Kafka安装
因为kafka是基于Zookeeper的,而Zookeeper一般都是一个分布式的集群,尽管kafka有自带Zookeeper,但是一般不使用自带的,都是使用外部安装的,所以首先我们需要安装Zooke ...
- mt19937
额,这个是一个小记.没什么,就是记给自己看的,你可以走了. mt19937 需要 C++11.生成高质量随机数. mt19937 rnd(chrono::system_clock::now().tim ...