Socket API
- 使用 IP + 端口号 标识通信端点
- 操作系统/进程使用文件描述符管理套接字 socket descriptor
- 类似于文件的抽象
- 当应用进程创建套接字时,操作系统分配一个数据结构存储该套接字相关信息
- 返回套接字描述符
Socket API 函数
创建socket
sd = scoket(protofamily, type, proto);
- 创建套接字
- 操作系统返回套接字描述符(sd)
- 第一个参数(协议族):AF_INET (TCP/IP)
- 第二个参数(套接字类型)
- SOCK_STREAM TCP 流式
- SOCK_DGRAM UDP
- SOCK_RAW 直接面向网络层的原始套接字
- 第三个参数(协议号):0 默认的协议
“sock_raw” 是一种特殊类型的套接字,通常用于在网络层级上进行原始数据包的读取和发送,而不经过传输层的处理。使用 sock_raw
套接字可以让程序直接访问网络层的数据,通常需要特权权限才能够操作。这种类型的套接字通常用于网络分析、数据包捕获、网络安全等领域。
关闭套接字
int closesocket(Socket sd)
- 关闭一个描述符为 sd 的套接字
- 如果多个进程共享一个套接字,调用
closesocket
将套接字引用计数减 1,减至 0 才关闭 - 一个进程中的多线程对一个套接字的使用无计数
- 如果进程中的一个线程调用
closecocket
将一个套接字关闭,该进程中的其他线程也将不能访问该套接字
- 如果进程中的一个线程调用
bind
绑定套接字的本地端点地址,客户端应用程序一般不需要调用 bind 函数,操作系统会帮助设置。int bind(sd, localaddr, addrlen)
INADDR_ANY
可以绑定所有网卡的 IP 地址,来自所有网卡的请求都能接受。
listen
int listen(sd, queuesize)
- 置服务端的流套接字处于监听状态
- 仅服务器调用
- 仅用于面向连接的流套接字
- 连接队列大小
connect
connect(sd, saddr, saddrlen)
- 客户端程序调用 connect 函数来使客户端套接字与特定计算机的特定端口的套接字进行连接
- 仅用于客户端
- 可用于 TCP 客户端也可以用于 UDP 客户端
- TCP 客户端:建立 TCP 连接 调用成功说明连接成功
- UDP 客户端:仅指定服务器端点地址(UDP 无连接),调用成功,不一定能发送消息
accept
newsock = accept(sd, caddr, caddrlen)
- 服务程序调用 accept 函数从处于监听状态的流套接字 sd 的客户连接请求队列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户套接字创建连接通道
- 仅用于 TCP 套接字
- 仅用于服务器
- 利用新创建的套接字与客户通信 (点对点)
send sendto
send(sd, *buf, len, flags)
sendto(sd, *buf, len, flags, destaddr, addrlen)
- send 函数用于 TCP 套接字(客户与服务器)或调用了 connect 函数的 UDP 客户端套接字
- sendto 函数用于 UDP 服务器端套接字与未调用 connect 函数的 UDP 客户端套接字
recv recvfrom
recv(sd, *buf, len, flags)
recvfrom(sd, *buf, len, flags, sendraddr, saddrlen)
- recv 函数从 TCP 连接的另一端接收数据,或者从调用了 connect 函数的 UDP 客户端套接字接收服务器来的数据
- recvfrom 函数用于从 UDP 服务器端套接字与未调用 connect 函数的 UDP 客户端套接字接收对端数据
setsockopt getsockopt
网络字节序列
- TCP/IP 定义了标准的用于协议头中的二进制整数表示:网络字节序(network byte order)
- 某些 Socket API 函数的参数需要存储网络字节序(IP,端口)
- htons:本地字节序转为网络字节序(16bits)
- ntohs: 网络字节序转为本地字节序(16bits)
- htonl:本地字节序转为网络字节序(32bits)
- ntohl:网络字节序转为本地字节序(32bits)
解析服务器 IP 地址
客户端可能使用域名或 IP 地址标识服务器,而 IP 协议需要用 32 位二进制 IP 地址,需要将域名或 IP 地址转为 32 位 IP 地址。
inet_addr
实现点分十进制 IP 地址到 32 位 IP 地址转化
gethostbyname
实现域名到 32 位 IP 地址转换
解析服务器(熟知)端口号
客户端还可能使用服务名(HTTP)标识服务器端口,需要将服务名转换为熟知端口。
getservbyname
解析协议号
协议名到协议号的转换