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源码的角度看 ...
随机推荐
- ThreadLocal的正确使用与原理
ThreadLocal是什么 ThreadLocal是线程Thread中属性threadLocals即ThreadLocal.ThreadLocalMap的管理者,ThreadLocal用于给每个线程 ...
- c++基础之虚函数表指针和虚函数表创建时机
虚函数表指针 虚函数表指针随对象走,它发生在对象运行期,当对象创建的时候,虚函数表表指针位于该对象所在内存的最前面. 使用虚函数时,虚函数表指针指向虚函数表中的函数地址即可实现多态. 虚函数表 虚函数 ...
- nim_duilib(17)之xml配置窗口调整大小
本文目标 xml配置窗口,使得窗口可以调整大小. sizebox windows的属性sizebo的作用就是设置窗口可以调整大小.鼠标放到窗口边缘,拖动窗口并改变大小. 一个例子 <Window ...
- 【LeetCode】734. Sentence Similarity 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 只修改区间起终点 日期 题目地址:https://le ...
- 【LeetCode】535. Encode and Decode TinyURL 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 解题方法 方法一:数组 方法二:字典 日期 题目地址:https://l ...
- 1161 - Extreme GCD
1161 - Extreme GCD PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 32 MB All ...
- 离线版centos8安装docker笔记
嗨嗨哈哈,已经很久没有坐下来胡编乱造一点笔记了,平时云服务器搞惯了,一个命令就安装好了docker了的,但这次生不逢时的新机房就没那么幸运了,有多不逢时超乎想象,不仅仅服务器没有外网,就连周围方圆一公 ...
- Google Chrome调整控制台的位置
众所周知,控制台是开发必备的工具,学会流畅的使用控制台会给我们的开发带来不一样的体验,但是控制台的位置有时却是困扰我们的一件事,控制台默认是在浏览器内,有时十分妨碍我们,那么有没有什么办法修改控制台的 ...
- Java——HashMap集合详解
第一章 HashMap集合简介 1.1 介绍 HashMap基于哈希表的Map接口实现,是以key-value存储形式存在,即主要用来存放键值对.HashMap 的实现不是同步的,这意味着它不是线程安 ...
- AVD Pixel_2_API_30 is already running. lf that is not the case, delete the files at
AVD Pixel_2_API_30 is already running. lf that is not the case, delete the files at C:\Users\Adminis ...