1、listen()队列剖析

作用:监听端口,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连接请求,同时拒绝为真实用户提供服务。
2、阻塞与非阻塞I/O

阻塞和非阻塞主要是指调用一个系统函数时,这个函数是否会导致进程进入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()的更多相关文章

  1. 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    [Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...

  2. Linux进程间通信(八):流套接字 socket()、bind()、listen()、accept()、connect()、read()、write()、close()

    前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket进行通信的进程可以是同一台计算机的进程,也是可以是通过网络连接起来的不同计算机上的进程.通常我们使用socket进行网络编 ...

  3. listen和accept函数

    listen函数是用来设置监听连接的句柄和队列 当listen函数执行完成以后,服务端就已经可以接受客户端来的新连接了,新连接完成以后listen会把客户端的ip,port和连接句柄放在监听队列里面, ...

  4. 【Linux 网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数:对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...

  5. 【转载】socket 的 connect、listen、accept 和全连接队列、半连接队列的原理

    转自:http://blog.csdn.net/tennysonsky/article/details/45621341 写在前面: 1. accept 只是从全连接队列拿出一个已经建立好的socke ...

  6. tcp通讯中socket套接字accept和listen的关系

    今天看到一个文章,客户端的connect在服务端调用accept之前,突然想到这可以建立正常的连接么?以前从没细细的思考过listen accept connect之前的关系,带着疑问学习了一下,记录 ...

  7. listen()

    创建一个套接口并监听申请的连接. #include <winsock.h> int PASCAL FAR listen( SOCKET s, int backlog); S:用于标识一个已 ...

  8. socket listen backlog

    http://stackoverflow.com/questions/4253454/question-about-listening-and-backlog-for-sockets The list ...

  9. 从Linux源码看Socket(TCP)的listen及连接队列

    从Linux源码看Socket(TCP)的listen及连接队列 前言 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 今天笔者就来从Linux源码的角度看 ...

随机推荐

  1. ThreadLocal的正确使用与原理

    ThreadLocal是什么 ThreadLocal是线程Thread中属性threadLocals即ThreadLocal.ThreadLocalMap的管理者,ThreadLocal用于给每个线程 ...

  2. c++基础之虚函数表指针和虚函数表创建时机

    虚函数表指针 虚函数表指针随对象走,它发生在对象运行期,当对象创建的时候,虚函数表表指针位于该对象所在内存的最前面. 使用虚函数时,虚函数表指针指向虚函数表中的函数地址即可实现多态. 虚函数表 虚函数 ...

  3. nim_duilib(17)之xml配置窗口调整大小

    本文目标 xml配置窗口,使得窗口可以调整大小. sizebox windows的属性sizebo的作用就是设置窗口可以调整大小.鼠标放到窗口边缘,拖动窗口并改变大小. 一个例子 <Window ...

  4. 【LeetCode】734. Sentence Similarity 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 只修改区间起终点 日期 题目地址:https://le ...

  5. 【LeetCode】535. Encode and Decode TinyURL 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 解题方法 方法一:数组 方法二:字典 日期 题目地址:https://l ...

  6. 1161 - Extreme GCD

    1161 - Extreme GCD    PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 32 MB All ...

  7. 离线版centos8安装docker笔记

    嗨嗨哈哈,已经很久没有坐下来胡编乱造一点笔记了,平时云服务器搞惯了,一个命令就安装好了docker了的,但这次生不逢时的新机房就没那么幸运了,有多不逢时超乎想象,不仅仅服务器没有外网,就连周围方圆一公 ...

  8. Google Chrome调整控制台的位置

    众所周知,控制台是开发必备的工具,学会流畅的使用控制台会给我们的开发带来不一样的体验,但是控制台的位置有时却是困扰我们的一件事,控制台默认是在浏览器内,有时十分妨碍我们,那么有没有什么办法修改控制台的 ...

  9. Java——HashMap集合详解

    第一章 HashMap集合简介 1.1 介绍 HashMap基于哈希表的Map接口实现,是以key-value存储形式存在,即主要用来存放键值对.HashMap 的实现不是同步的,这意味着它不是线程安 ...

  10. 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 ...