ServerSocket Accept 一些理解

当我们调用如下代码的时候,实际java封装了很多层调用

图1

new ServerSocket(9876) 这个构造函数的内部,会调用 bind() 以及 listen() 等系统调用,之后才是 accept(),下面依次讲解。

bind(): bind 只是简单的将套接字和 地址端口联系上,调用bind()之后,netstat 不会看到任何连接

listen(): listen 表示此套接字 已经处于监听状态了,外部请求可以打进来了。


图2

可以看到,并没有运行到 accept() ,socket已经处于监听状态了,那此时如果外部连接打进来会怎样呢?我们用浏览器模拟http请求。 打开 chrome 输入 127.0.0.1:9876 回车,


图3

可以看到 55870 端口建立了连接 (ESTABLISHED 表示连接已经建立)  (55868那个端口不知道怎么来的,有知道的大神希望能指点一下)。然后我们在浏览器多开几个窗口输入,会发现连接建立的更多了。


图4

所以,listen的时候,是可以接收请求并建立连接的,只是不处理这个socket的内容而已。参考UNIX网络编程(卷一,套接字联网API 第三版 p85),此时系统维护两个队列,未完成建立连接队列(三次握手只进行了第一步)和 已完成建立连接队列(上述ESTABLISTHED的连接)。而之后的 accept() 会在已建立连接队列获取套接字来处理。

accept() :会从上述已建立连接套接字队列,获取队列头部的socket,来进行处理,每次accept()都会返回一个对应客户端的全新socket 。当建立连接队列为空时,accept会阻塞并处于睡眠状态。

另注:当accept() 之后,如果一个请求打过来,服务器处理请求之后,并不会将连接中断,而是会一直通过 客户端的 keepAlived 来维持这个连接


图4

可以看到  都是从客户端发送的 keepalived 请求,服务端回应ack。

补充一下:在listen之前,创建的socket都默认为要主动 connect 其他服务的,即为主动socket,只有listen 之后,socket 才变为被动的。服务端的socket 都是listen了之后,才变为服务socket的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。