字节序函数
#include <netinet/in.h> /* 主机序转换为网络序(short类型) */ uint16_t htons (uint16_t host16bitvalue); /* 主机序转换为网络序(long类型) */ uint32_t htonl (uint32_t host32bitvalue);
/* 网络序转换为主机序(short类型) */ uint16_t ntohs (uint16_t net16bitvalue); /* 网络序转换为主机序(long类型) */ uint32_t ntohl (uint32_t net32bitvalue);
|
字节操纵函数
#include <string.h> /* 清零 */ void bzero (void *dest, size_t nbytes); /* 拷贝 */ void bcopy (const void *src, void *dest, size_t nbytes); /* 比较 */ int bcmp (const void *ptr1, const void *ptr2, size_t nbytes);
|
IPv4地址转换函数
#include <arpa/inet.h>
/* * 字符串(x.x.x.x)转为32位网络序数值 * 返回:成功 - 1, 失败 - 0 */ int inet_aton (const char *strptr, struct in_addr *addrptr);
/* * 字符串(x.x.x.x)转为32位网络序数值 * 返回:成功 - 32位网络序数值,失败 - INADDR_NONE(0xffffffff) * 注意:255.255.255.255地址无法转换,不推荐使用 */ in_addr_t inet_addr (const char *strptr);
/* * 32位网络序数值转为字符串(x.x.x.x) * 返回:字符串(x.x.x.x) * 注意:返回的字符串保存在静态内存中,此函数不可重入 */ char* inet_ntoa (struct in_addr inaddr);
|
IPv4、IPv6 通用地址转换函数
#include <arpa/inet.h> /* * 地址字符串转为数值 * 参数:family - AF_INET; AF_INET6, addrptr - sockaddr_in结构体的sin_addr的地址或sockaddr_in6结构体的sin6_addr的地址 * 返回:成功 - 1,失败 - -1,输入不是有效的地址 - 0 */ int inet_pton (int family, const char *strptr, void *addrptr); /* * 数值转为地址字符串 * 参数:family - AF_INET或AF_INET6, addrptr - sockaddr_in结构体的sin_addr的地址或sockaddr_in6结构体的sin6_addr的地址 strptr - 保存转换后的地址字符串,指针不能为空,并不小于len指定的长度 len - 字符串长度,中定义INET_ADDRSTRLEN(16)或INET6_ADDRSTRLEN(48) * 返回:成功 - 返回strptr,失败 - NULL */ const char* inet_ntop (int family, const void *addrptr, char *strptr, size_t len);
|
TCP套接口函数
#include <sys/socket.h> /* * 创建socket套接口,指定套接口协议类型 * 参数: family - AF_UNIX(Unix域),AF_LOCOL(Unix域的POSIX名称),AF_INET(IPv4),AF_INET6(IPv6),AF_ROUTE(路由套接口),AF_KEY(密钥套接口),AF_PACKET type - SOCK_STREAM(字节流),SOCK_DGRAM(数据报),SOCK_RAW(原始IPv4、IPv6),SOCK_PACKET(LINUX上类似BPF(BSD分组过滤器,Berkeley内核,如FreeBSD)和DLPI(数据链路提供者接口,SVR4内核,如soloris)的直接访问底层数据链路的套接口类型),SOCK_RDM(可靠传递消息),SOCK_SEQPACKET(有序分组) protocol - 0为给定family和type组合的系统默认值 返回:成功 - 套接口描述字,失败 - -1 */ int socket (int family, int type, int protocol);
/* * TCP客户端与TCP服务器建立连接,调用此函数会触发TCP的三次握手,并建立连接。调用此函数前,不必调用bind函数,内核会决定源IP并选择一个临时端口作为源端口。 * 参数: sockfd - 套接口描述字 servaddr - 包含要连接的服务器的IP和端口号的套接口地址结构 addrlen - servaddr套接口地址结构体的大小 * 返回:成功 - 0,失败 - -1 */ int connect (int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
/* * 将一个本地协议地址赋给套接口 * 参数: sockfd - 套接口描述字 myaddr - 绑定的本地协议地址,对于网际协议,即IP地址和端口,如果IP地址赋值为INADDR_ANY(通配地址wildcard),则由内核去选择IP地址,如果端口赋值为0,则由内核选择一个临时端口 addrlen - 地址结构体的大小 * 返回:成功 - 0,失败 - -1 */ int bind (int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
/* * 指示内核接受一个未连接的套接口上的连接请求 * 参数: sockfd - 套接口描述字 backlog - 套接口两个队列(完成连接和未完成连接)的排队最大连接个数,各个操作系统有不同的根据backlog计算排队最大连接个数的算法 返回:成功 - 0, 失败 - -1 */ int listen (int sockfd, int backlog);
/* * 从已完成连接队列对头返回一个已完成连接,如果已完成连接队列为空,那么进程被阻塞(假设套接口为缺省的阻塞方式) * 参数: sockfd - 监听套接口描述字 cliaddr - 输出参数,返回已连接的客户端的协议地址,为NULL,则不返回 addrlen - 输出参数,返回套接口地址结构体的大小,为NULL,则不返回 * 返回:成功 - 已连接套接口描述字(由内核自动生成的一个新描述字,代表与所返回客户端的TCP连接),失败 - -1, EINTER - 收到中断 */ int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
#include <unistd.h> /* * 关闭套接口,并终止TCP连接,如果为并发服务器父进程关闭已连接套接口,会将相应描述字的引用计数减一,如果计数不为0,将不会发送FIN * 参数:sockfd - 套接口描述字 * 返回:成功 - 0, 失败 - -1 */ int close (int sockfd);
|
获得与套接口关联的协议地址
#include <sys/socket.h> /* * 获得与套接口关联的本地协议地址 * 参数: sockfd - 套接口描述字 localaddr - 输出参数,返回与套接口关联的本地协议地址 addrlen - 输出参数,返回套接字地址结构体的大小 * 返回:成功 - 0, 失败 - -1 */ int getsockname (int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
/* * 获得与套接口关联的远端协议地址 * 参数: sockfd - 套接口描述字 peeraddr - 输出参数,返回与套接口关联的远端协议地址 addrlen - 输出参数,返回套接字地址结构体的大小 * 返回:成功 - 0, 失败 - -1 */ int getpeername (int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
|
I/O 复用函数
#include <sys/select.h> #include <sys/time.h>
/* * 检查是否收到关心的套接字事件 * 参数: maxfdp1 - 关心的最大套接字 + 1 readset - 关心是否可读的套接字的集合,NULL代表不关心 writeset - 关心是否可写的套接字的集合,NULL代表不关心 exceptset - 关心是否有异常的套接字的集合,NULL代表不关心 timeout - NULL:永远等下去;秒数和毫秒数都为0:不等待;指定值:等待一段时间 * 返回:成功 - 就绪套接字的数目,超时 - 0,失败 - -1 */ int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);
/* 用来设置关心套接字集合的函数 */ void FD_ZERO(fd_set *fdset); void FD_SET(int fd, fd_set *fdset); void FD_CLR(int fd, fd_set *fdset); int FD_ISSET(int fd, fd_set *fdset);
|
发送FIN函数
#include <sys/socket.h>
/* * 发送FIN,关闭连接 * 参数: sockfd - 要关闭连接的socket描述字 howto - 关闭连接方式:SHUT_RD - 关闭连接的读这一半,不再接收数据,丢弃接收缓冲区中的未接收数据;SHUT_WR - 关闭连接的写这一半,即半关闭状态,发送缓冲区中将被发送完;SHUT_RDWR - 连接的读写都被关闭 * 返回:成功 - 0,失败 - -1 */ int shutdown(int sockfd, int howto);
|
套接口选项函数
注:标志表明了该选项是否为启用或禁止类型,0 - 禁止,非0 - 启用
级别 |
选项名 |
get |
set |
说明 |
标志 |
数据类型 |
SOL_SOCKET |
SO_BROADCAST |
* |
* |
开启或禁止进程发送广播消息的能力,只适用于UDP套接口,如果目的地址为一个广播地址且本套接口选项没有设置,则返回EACCES错误 |
* |
int |
|
SO_DEBUG |
* |
* |
只适用于TCP套接口,对套接口发送和接受的报文保留详细跟踪信息,可使用trpt程序进行查看 |
* |
int |
|
SO_DONTROUTE |
* |
* |
对发出的报文不查询路由表,直接通过目的地址的网络地址确定本地接口后发送,如果无法由目的地址确定(即不在一个点到点链路或共享网络),则返回ENETUNREACH错误 |
* |
int |
|
SO_ERROR |
* |
|
当socket发生错误时,可以同访问SO_ERROR套接口选项获取该错误值(保存在so_error中),读取后so_error被复位为0,该错误被称为待处理错误(pending error) |
|
int |
|
SO_KEEPALIVE |
* |
* |
适用于TCP套接口,启用或禁止2小时内未收到任一方向上的数据则发送保活探测报文 |
* |
int |
|
SO_LINGER |
* |
* |
指定close函数对面向连接协议(如TCP和SCTP)如何操作,缺省操作是close函数立即返回,如果发送缓冲区有数据,则尝试发送给对端。SO_LINGER选项可以改变此设置。
如果l_onoff为0,使用缺省设置。
如果l_onoff为非0且l_linger为0,则丢弃发送缓冲区中的数据并发送一个RST给对端,没有通常的四次握手终止连接
如果l_onoff为非0且l_linger为非0,则当套接口关闭时内核将拖延一段时间,如果发送缓冲区有数据,进程将被阻塞,知道所有数据发送玩且均被对方确认或延滞时间到。如果套接口为非阻塞型,那么它将不等待close完成,即使l_linger为非0。 |
|
sturct linger {
int l_onoff;
int l_linger;
} |
|
SO_OOBINLINE |
* |
* |
开启时,带外数据将被留在正常的输入队列中。这种情况下接收函数的MSG_OOB标志不能用来读带外数据。 |
* |
int |
|
SO_RCVBUF |
* |
* |
改变接收缓冲区的缺省大小,对于TCP客户端的接受缓冲区大小必须在调用connect之前设置;对于TCP服务器端必须在调用listen之前给套接口设置,新建的已连接套接口从监听套接口继承缓冲区大小。TCP缓冲区大小至少应是相应连接的MSS值的四倍,且为MSS值的偶数倍。 |
|
int |
|
SO_SNDBUF |
* |
* |
改变发送缓冲区的缺省大小,同上 |
|
int |
|
SO_RCVLOWAT |
* |
* |
改变接收低潮标记,即select返回套接口接收缓冲区可读所需的数据量,对于TCP、UDP、SCTP套接口,缺省为1 |
|
int |
|
SO_SNDLOWAT |
* |
* |
改变发送低潮标记,即select返回套接口发送缓冲区可写所需的可用空间 |
|
int |
|
SO_RCVTIMEO |
* |
* |
改变套接口接收的超时值,时间为0代表不超时 |
|
struct timeval |
|
SO_SNDTIMEO |
* |
* |
改变套接口发送的超时值,时间为0代表不超时 |
|
struct timeval |
|
SO_REUSEADDR |
* |
* |
允许启动一个监听服务器并捆绑众所周知端口,即使以前在此端口上建立的连接仍存在;允许完全重复的捆绑:即当一个IP地址和端口已绑定到某个套接口上时,如果传输协议支持,同样的IP和端口还可以捆绑到另一个套接口上,一般来说仅支持UDP套接口。 |
* |
int |
|
SO_REUSEPORT |
* |
* |
允许完全重复的捆绑(如上详述),不过只有在想要捆绑同一IP地址和端口的每一个套接口都启用本选项才行;如果被捆绑的IP地址是一个多播地址,那么SO_REUSEADDR和SO_REUSEPORT被认为等效 |
* |
int |
|
SO_TYPE |
* |
|
获得套接口的类型,如SOCK_STREAM或SOCK_DGRAM |
|
int |
|
SO_USELOOPBACK |
* |
* |
只适用于路由域套接口,开启时,相应套接口将接收在其上发送的任何数据报的一份拷贝 |
* |
int |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <sys/socket.h>
/* * 获得套接口选项 * 参数: sockfd - 套接字,level - 级别,optname - 选项名,optval - 值,optlen - 值的大小 * 返回: 0 - 成功,-1 - 失败 */ int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
/* * 设置套接口选项 * 参数: sockfd - 套接字,level - 级别,optname - 选项名,optval - 值,optlen - 值的大小 * 返回: 0 - 成功,-1 - 失败 */ int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t *optlen);
|
套接字控制操作
控制操作 |
命令 |
参数 |
返回 |
设置套接口为非阻塞I/O型 |
F_SETFL |
O_NONBLOCK |
成功 - 0,失败 - -1 |
设置套接口为信号驱动I/O型 |
F_SETFL |
O_ASYNC |
|
获得套接口文件标志 |
F_GETFL |
0 |
成功 - 文件标志,失败 - -1 |
设置套接口拥有者,用于接收SIGIO和SIGURG信号 |
F_SETOWN |
进程ID或进程组ID |
成功 - 0,失败 - -1 |
获得套接口拥有者 |
F_GETOWN |
0 |
成功 - 进程ID或进程组ID,失败 - -1 |
#include <fcntl.h>
/* * 套接字控制操作 * 参数:fd - 套接字,cmd - 命令 * 返回:依赖cmd(见上表) */ int fcntl(int fd, int cmd, .../* int arg */);
|
UDP套接口函数
#include <sys/socket.h>
/* * 接收UDP报文 * 参数: sockfd - 套接字 buff - 指向接收缓存的地址 nbytes - 接收字节数 flags - from - 返回UDP报文发送者的套接口地址 addrlen - 返回from套接口地址的大小 * 返回:成功返回接收的字节数,出错返回-1 */ ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen);
/* * 发送UDP报文 * 参数: sockfd - 套接字 buff - 指向发送缓存的地址 nbytes - 发送字节数 flags - to - UDP报文接收者的套接口地址 addrlen - to套接口地址的大小 * 返回:成功返回发送的字节数,出错返回-1 */ ssize_t sendto(int sockfd, void *buff, size_t nbytes, int flags, const struct sockaddr *to, socklen_t addrlen);
| |
|