什么是 Socket ?
写于2025-03-11 | 首发于 知乎
Socket 的定义
什么是 socket ?
Definition: A socket is one endpoint of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent to. (参考资料:Oracle - What Is a Socket?)
来源与历史
Socket API 是由计算机的操作系统封装提供的。不同的系统设计和实现的过程有细微差别。
操作系统的 Socket API 最早可以追溯到加州大学伯克利分校(UC Berkeley)开发的 Berkeley Sockets(简称 BSD Sockets)。它最初在 1982 年作为 BSD 4.1c 操作系统的一部分首次发布。这种 API 设计简单而强大,成为了网络编程的事实标准,并被广泛应用于 Unix 系统及其衍生版本中。 参考资料:socket发展史
在实际开发过程中,操作系统开发者会基于 BSD Sockets 的设计实现或扩展 Socket API,以满足不同平台的需求:
Unix 和 Linux:直接继承了 BSD Sockets 的设计,并在内核中实现了相关的网络协议栈。
Windows:微软开发了 Windows Sockets API(简称 Winsock),它基于 BSD Sockets,但为了适应 Windows平台的特点进行了扩展。Winsock 的开发是由多家公司合作完成的,包括微软、Novell 和 Sun Microsystems 等。
为了实现跨平台兼容性,现代操作系统和编程语言都遵循了一些标准化的接口设计:
- POSIX 标准:许多操作系统(如 Linux 和 macOS)遵循 POSIX 标准来实现 Socket API,从而确保了跨平台的兼容性。
- 编程语言的封装:如 Java 和 Python 等语言,通过内置的 Socket 类库,为开发者提供了统一的接口,隐藏了底层操作系统的差异。
Socket API 的功能
Socket API 主要面向网络分层结构中的传输层的相关协议,尤其是TCP和UDP。在传输层协议之外,Socket API也会间接与网络层协议(如 IP(Internet 协议))交互。
计算机网络的层次结构及相关协议如下: 
计算机网络的连接通信基本流程如下: 
(图片参考博客:简单理解socket)
Socket API 提供了创建 TCP 连接、发送和接收数据、关闭连接等功能,以及收发 UDP 数据报的功能。
其通过指定 IP 地址和端口号来建立连接或发送数据报,从而间接使用 IP 协议。在 Socket 编程中,IP 地址用于标识网络上的主机,而端口号用于标识主机上的应用程序。
Socket API 还可以与一些其他协议或功能结合使用:
- IPv4 和 IPv6: Socket API 支持 IPv4 和 IPv6 地址族(AF_INET 和 AF_INET6),允许应用程序在 IPv4 和 IPv6 网络中进行通信。
- ICMP(Internet 控制消息协议):虽然 ICMP 主要用于网络管理(如 ping 命令),但在某些情况下,Socket API 也可以用于发送和接收 ICMP 消息(例如,通过原始套接字)。
- 多播和广播:Socket API 支持多播(multicast)和广播(broadcast)功能,允许应用程序向多个目标发送数据。
Socket API 的类型与协议
Socket API 提供了不同的套接字类型,用于支持不同的协议:
- SOCK_STREAM:面向连接的套接字类型,对应于 TCP 协议。提供可靠的字节流服务。
- SOCK_DGRAM:无连接的套接字类型,对应于 UDP 协议。提供不可靠的数据报服务。
- SOCK_RAW:原始套接字,允许直接访问底层协议(如 IP 或 ICMP)。通常用于开发网络工具或协议分析。
编程语言中的 Socket 类
编程语言中的 Socket 类 是通过语言的运行时环境(Runtime Environment)或标准库(Standard Library)来对接操作系统的 Socket API 的。
具体来说,语言的 Socket 类封装了底层操作系统的系统调用(System Calls),使得开发者可以通过高级语言的接口来访问和操作 Socket,而无需直接调用底层的系统调用。以下是具体的实现方式和过程:
- 语言运行时环境的作用: 编程语言的运行时环境通常会提供一个抽象层,用于与操作系统的底层功能进行交互。 对于 Socket 编程,运行时环境会封装操作系统的 Socket API,使得语言能够以一种与平台无关的方式访问网络功能。
- 封装过程: 编程语言的 Socket 类封装了操作系统的 Socket API,主要通过以下几种方式实现:
(1)系统调用封装:语言的运行时环境或标准库会封装操作系统的系统调用。
示例: • 在 C/C++ 中, socket() 、 bind() 、 listen() 、 accept() 等函数直接对应操作系统的系统调用。 • 在 Python 中, socket.socket() 方法调用了底层的 socket() 系统调用,而 socket.bind()、socket.listen() 等方法则是对相应系统调用的封装。
(2)抽象类和方法:语言的 Socket 类通常会提供一个抽象的接口,隐藏底层的复杂性。
示例: • Python 的 socket 模块提供了一个 socket 类,通过方法(如 connect() 、send() 、recv() )封装了底层的 Socket 操作。 • Java 的 java.net.Socket 类提供了方法(如 connect() 、getInputStream()、getOutputStream() )来封装底层的 Socket 操作。
(3)跨平台兼容性:为了确保跨平台兼容性,语言的 Socket 类会根据运行的操作系统选择合适的底层实现。
示例: • Python 和 Java 的 Socket 类在不同操作系统上会调用不同的底层实现,但对开发者来说,接口保持一致。 • C/C++ 的 Socket 编程在不同操作系统上可能需要使用不同的头文件和库(如 Windows 使用 Winsock ,而 Unix/Linux 使用 POSIX 标准的 Socket API)。
java中socket的简单实现如下:
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
Socket sock = new Socket("127.0.0.1", 8080); // 创建 Socket 并连接服务器
sock.getOutputStream().write("Hello".getBytes()); // 发送数据
sock.close(); // 关闭 Socket
}
}