Java Socket 工作机制

Socket 连接机制

主机 A 的应用程序要能和主机 B 的应用程序通信,必须通过 Socket 建立连接,而建立 Socket 连接必须由底层 TCP/IP 来建立TCP连接。TCP 是因特网中的传输层协议,使用三次握手协议建立连接。当请求方发出 SYN 连接请求后,等待对方回答 SYN+ACK ,并最终对对方的 SYN 执行 ACK(Acknowledgement确认字符)确认。

 

三次握手协议

第一次握手:客户端发送 SYN(SEQ=x)报文给服务器端,进入 SYN_SEND 状态。

第二次握手:服务器端收到 SYN 报文,回应一个 SYN (SEQ=y)ACK(ACK=x+1)报文,进入 SYN_RECV 状态。

第三次握手:客户端收到服务器端的 SYN 报文,回应一个 ACK(ACK=y+1)报文,进入 Established 已建立状态。

 

Socket连接过程

客户端

当客户端要与服务端通信时,客户端首先要创建一个 Socket 实例,操作系统将为这个 Socket 实例分配一个没有被使用的本地端口号,并创建一个包含本地地址、远程地址和端口号的套接字数据结构,这个数据结构将一直保存在系统中直到这个连接关闭。

在创建 Socket 实例的构造函数正确返回前,将要进行 TCP 的三次握手协议,TCP握手完成后,Socket实例对象创建完成,否则抛出IOException。

服务端

与客户端对应的服务端将创建一个 ServerSocket 实例。同时操作系统也会为 ServerSocket 实例创建一个底层数据结构,包含指定监听的端口号和监听地址的通配符,之后当调用 accept() 方法时,将进入阻塞状态,等待客户端请求。

当请求到来时,将为这个连接创建一个新的套接字数据结构,其中包含了请求源的地址和端口号。这个数据结构会关联到ServerSocket 实例的一个未完成的连接列表中。注意此时服务端的 ServerSocket 实例还未创建完成,要等到与客户端的三次握手完成后这个服务端的ServerSocket实例才会返回,并将其对应的数据结构从未完成列表转移到已完成列表。

数据传输

当连接建立成功后,客户端和服务端都会拥有一个 Socket 实例,每个 Socket 实例都有一个 InputStream 和 OutputStream,并通过这两个对象以字节流交换数据。

当创建 Socket 实例时,操作系统会为 InputStream 和 OutputStream 分配一定大小的缓冲区,发送端将数据写到 OutputStream的 SendQ 队列中,当 SendQ 满了,数据将被转移到到另一端的 InputStream 的 RecvQ 队列中,若 RecvQ 也满了,那么OutputStream 的 write 方法将阻塞,直到 RecvQ 有足够空间容纳 SendQ 发送的数据。若两边同时传输数据可能会产生死锁。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章