socket API
socket API概述
socket是网络通信端点的抽象,可用于网络间进程通信接口,Linux下socket接口主要可以分为以下几种:
- socket地址API:socket地址,指定通信的端点,包括:
- 字节序转换(
htonl
/htons
/ntohl
/ntohs
) - 地址结构体(
sockaddr
/sockaddr_un
/sockaddr_in
/sockaddr_in6
) - 地址转换(
inet_ntop
/inet_pton
)
- 字节序转换(
- socket基础API:socket通信常用操作,包括:
- 创建socket(
socket
) - 地址绑定(
bind
) - 监听socket(
listen
) - 接受链接(
accept
) - 发起连接(
connect
) - 读写数据(
send
/recv
/sendto
/recvfrom
) - 关闭连接(
close
/shutdown
) - 地址获取(
getsockname
) - socket选项设置(
getsockopt
/setsockopt
)
- 创建socket(
- 网络信息API:
- 主机名/IP地址转换(
gethostbyname
/gethostbyaddr
) - 服务名/端口号转换(
getservbyname
/getservbyport
)
- 主机名/IP地址转换(
socket可以支持不同的地址族和socket类型,但是TCP/IP栈的应用是最多的,一个最简单的TCP/IP socket应用就是C/S模型:一个服务器通过socket向多个客户端提供它们所需的资源,具体步骤如下图所示:
socket 地址 API
字节序
PC机与网络传输时使用的字节序是不同的
- 主机字节序:小端字节序,低位字节位于低地址,高位字节位于高地址
- 网络字节序:大端字节序,高位字节位于低地址,低位字节位于高地址
字节序转换函数:h(主机字节序);n(网络字节序);l(unsigned long int);s(unsigned short int)
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong); // 小端->大端
uint16_t htons(uint16_t hostshort); // 小端->大端
uint32_t ntohl(uint32_t netlong); // 大端->小端
uint16_t ntohs(uint16_t netshort); // 大端->小端
socket地址及转换
之前说了socket地址依赖不同的地址族(AF_INET
,AF_INET6
,AF_UNIX
)。具体的话,socket使用一个sockaddr
结构体通用表示不同地址簇的地址,在bind
函数中会再见到他:
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
sa_family
指定了该socket使用哪一个地址簇,而不同的地址簇又有自己的专用socket地址结构,在传参时通过强制类型转换到通用socket地址结构体sockaddr
,而解析sockaddr
变量时,通过读取sa_family
,再强制类型转换到对应专用地址结构体。
这里仅给出AF_INET
(IPv4)定义的专用地址结构体,其余两种看书。注意结构体中IP地址和端口号都是按网络字节序存储:
struct sockaddr_in {
sa_family_t sin_family; /* 地址族: AF_INET */
in_port_t sin_port