- 创建未连接套接字:
接口声明:int socket(int domain, int type, int protocol);
参数:
domain:域。
AF_INET/PF_INET:网际协议
AF_UNIX/PF_UNIX:本地协议,可写成AF_LOCAL/PF_LOCAL
type:类型。
SOCK_STREAM:流式套接字
SOCK_DGRAM:数据包套接字
protocol:协议。
一般为0
返回值:
成功:待连接套接字
失败:-1
备注:在网际协议中,选择流式套接字就代表TCP协议,选择数据包套接字就代表UDP协议,第三个参数protocol一般都不用。
======================================================
2、绑定套接字与网络地址
接口声明:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
sockfd:待连接套接字
addr:包含本地地址(IP+PORT)的通用地址结构体的指针
addrlen:地址结构体大小
返回值:
成功:0
失败:-1
备注:
通用地址结构体的定义:
struct sockaddr
{
sa_family_t sa_family; -> 协议 -> 2
char sa_data[14]; -> IP、端口号..
};
特殊地址结构体 —— IPv4地址结构体:
struct sockaddr_in
{
u_short sin_family; // 地址族 -> 2
u_short sin_port; // 端口号 -> 2
struct in_addr sin_addr; // IPV4地址 -> 4
char sin_zero[8];
};
struct in_addr
{
in_addr_t s_addr; // 无符号32位网络地址 -> IP
};
- 将待连接套接字设置为监听套接字,并设置最大同时接收连接请求个数
接口声明:int listen(int sockfd, int backlog);
参数:
sockfd:待连接套接字
backlog:最大同时接收连接请求个数
返回值:
成功:0,并将sockfd设置为监听套接字
失败:-1
备注:
由于历史原因,各种系统对backlog的理解并不一致,以LINUX为例,监听端能同时接收的最大连接请求个数为backlog+4
======================================================
4、等待对端连接请求
接口声明:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数:
sockfd:监听套接字
addr:通用地址结构体,用以存储对端地址(IP+PORT)
addrlen:参数addr的存储区域大小
返回值:
成功:已连接套接字(非负整数)
失败:-1
======================================================
5、连接对端监听套接字
接口声明:int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
sockfd:待连接套接字
addr:包含对端地址(IP+PORT)的通用地址结构体的指针
addrlen:地址结构体大小
返回值:
成功:0
失败:-1
======================================================
- 断开本端连接套接字
接口声明:int close(int fd);
参数:
fd:已连接套接字
返回值:
成功:0
失败:-1
备注:
同时断开读端和写端
======================================================
7.1、将文本地址转化为二进制地址
接口声明:int inet_pton(int af, const char *src, void *dst);
参数:
af:地址族。AF_INET:IPv4地址
src:指向“点分式”IPv4或IPv6地址的指针,例如“192.168.1.100”
dst:类型为struct in_addr *的指针
返回值:
成功:1
失败:0代表地址与地址族不匹配,-1代表地址不合法
7.2、将二进制地址转化为文本地址
接口声明:const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
参数:
af:地址族。
AF_INET:IPv4地址
AF_INET6:IPv6地址
src:类型为struct in_addr *或者struct in6_addr *的指针
dst:地址缓冲区指针,缓冲区至少
size:地址缓冲区大小,至少要INET_ADDRSTRLEN或者INET6_ADDRSTRLEN个字节
返回值:
成功:dst
失败:NULL
======================================================
8.1、向TCP套接字发送数据
接口声明:ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数:
sockfd:已连接套接字
buf:即将被发送的数据
len:数据长度
flags:发送标志,置为0即可以。
返回值:
成功:已发送字节数
失败:-1
8.2、向UDP套接字发送数据
接口声明:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
参数:
sockfd:UDP套接字
buf:即将发送的数据
len:数据的长度
flags:发送标志,与函数send的flags完全一致
dest_addr:对端网络地址
addr_len:地址长度
返回值:
成功:已发送字节数
失败:-1
======================================================
9.1、从TCP套接字接收数据
接口声明: ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数:
sockfd:已连接套接字
buf:存储数据缓冲区
len:缓冲区大小
flags:接收标志,置为0即可以。
返回值:
成功:已接收字节数
失败:-1
9.2、从UDP套接字接收数据
接口声明:ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
参数:
sockfd:UDP套接字
buf:储存数据缓冲区
len:缓冲区大小
flags:接收标志,与函数send的flags完全一致
src_addr:对端网络地址
addrlen:地址长度
返回值:
成功:已接收字节数
失败:-1
======================================================
10.1、多路复用
接口声明:int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
参数:
nfds:所有正在监测的套接字的最大值加1
readfds:读就绪文件描述符集合
writefds:写就绪文件描述符集合
exceptfds:异常就绪文件描述符集合
timeout:超时控制
返回值:
成功:就绪文件描述符总数(当超时返回时为0)
失败:-1
备注:
文件描述符集合操作函数:
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
- 字节序转换
接口声明:
uint32_t htonl(uint32_t hostlong); //h -> host 主机(本地) n ->net 网络
uint16_t htons(uint16_t hostshort); //l -> long 长4 s -> short 短2
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
参数:
hostlong: 主机字节序的长整型数据
hostshort: 主机字节序的短整型数据
netlong: 网络字节序的长整型数据
netshort: 网络字节序的短整型数据
返回值:
对应的字节序数据