网络套接字(Socket)
前言
在同一台计算机,进程之间可以这样通信,如果是不同的计算机呢?网络上不同的计算机,也可以通信,有学传输层协议TCP、UDP,它们就是用来在不同计算机之间通行的协议,但它们毕竟只是协议,看不见摸不着,那怎们通过TCP、和UDP进行实际传输呢?
答案是使用网络套接字(Socket)
概述
Socket 中文意思为插座的意思,专业术语称之为套接字,它把 TCP/IP 封装成了调用接口供开发者调用,也就是说开发者可以通过调用Socket相关API来实现网络通讯。
Socket 就像一个电话插座,负责连通两端的电话,进行点对点通信,让电话可以进行通信,端口就像插座上的孔,端口不能同时被其他进程占用。而建立连接就像把插头插在这个插座上,创建一个 Socket 实例开始监听后,这个电话插座就时刻监听着消息的传入,谁拨通我这个“IP 地址和端口”,我就接通谁。
实际上,Socket 是在应用层和传输层之间的一个抽象层,它把 TCP/IP 层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信。
Socket 起源于 UNIX,在 UNIX 一切皆文件的思想下,进程间通信就被冠名为文件描述符(file descriptor),Socket 是一种“打开—读/写—关闭”模式的实现,服务器和客户端各自维护一个“文件”,在建立连接打开后,可以向文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。
Socket 接口
socket(): 创建socket
bind(): 绑定socket到本地地址和端口,通常由服务端调用
listen(): TCP专用,开启监听模式
accept(): TCP专用,服务器等待客户端连接,一般是阻塞态
connect(): TCP专用,客户端主动连接服务器
send(): TCP专用,发送数据
recv(): TCP专用,接收数据
sendto(): UDP专用,发送数据到指定的IP地址和端口
recvfrom(): UDP专用,接收数据,返回数据远端的IP地址和端口
closesocket(): 关闭socket
更多详细参考socket接口详解
通信过程
Socket 保证了不同计算机之间的通信,也就是网络通信。对于网站,通信模型是服务器与客户端之间的通信。两端都建立了一个 Socket 对象,然后通过 Socket 对象对数据进行传输。通常服务器处于一个无限循环,等待客户端的连接。
面向连接的 TCP 时序图:
从 TCP 连接的视角看 Socket 过程
TCP 三次握手的 Socket 过程:
- 服务器调用 socket()、bind()、listen() 完成初始化后,调用 accept() 阻塞等待;
- 客户端 Socket 对象调用 connect() 向服务器发送了一个 SYN 并阻塞;
- 服务器完成了第一次握手,即发送 SYN 和 ACK 应答;
- 客户端收到服务端发送的应答之后,从 connect() 返回,再发送一个 ACK 给服务器;
- 服务器 Socket 对象接收客户端第三次握手 ACK 确认,此时服务端从 accept() 返回,建立连接。
TCP 四次挥手的 Socket 过程:
- 某个应用进程调用 close() 主动关闭,发送一个 FIN;
- 另一端接收到 FIN 后被动执行关闭,并发送 ACK 确认;
- 之后被动执行关闭的应用进程调用 close() 关闭 Socket,并也发送一个 FIN;
- 接收到这个 FIN 的一端向另一端 ACK 确认。
代码
Java版可以看这个理解搞了两周Socket通信,终于弄明白了!
参考链接