参考《Linux高性能服务器编程》
字节序
#include <arpa/inet.h>
//htonl 把unsigned long类型从主机序转换到网络序
uint32_t htonl(uint32_t hostlong);
//htons 把unsigned short类型从主机序转换到网络序
uint16_t htons(uint16_t hostshort);
//ntohl 把unsigned long类型从网络序转换到主机序
uint32_t ntohl(uint32_t netlong);
//ntohs 把unsigned short类型从网络序转换到主机序
uint16_t ntohs(uint16_t netshort);
ip转换
#include <arpa/inet.h>
//点分十进制转二进制
int inet_pton(int family, const char *strptr, void *addrptr);
//二进制转点分十进制
const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
- family:AF_INET(ipv4)、AF_INET6(ipv6)
- strptr:点分十进制字符串
- addrptr:二进制地址
- len:strptr需要的大小
地址结构体
-
通用地址结构
#inlcude <bits/socket.h> struct sockaddr { sa_family_t sa_family; char sa_data[14]; }; struct sockaddr_storage { sa_family_t sa_family; unsigned long int __ss_align; char __ss_padding[128-sizeof(__ss_align)]; //用于结构体对齐 };
-
专用地址结构体
#include <sys/un.h> // unix域 struct sockaddr_un { sa_family_t sun_family; // 地址族:AF_UNIX char sun_path[108]; // 文件路径名 }; // IPv4 struct sockaddr_in { sa_family_t sin_family; // 地址族:AF_INET u_int16_t sin_port; // 端口号,用网络字节序表示 struct in_addr sin_addr; // IPv4地址结构体 }; struct in_addr { u_int32_t s_addr; // IPv4地址,用网络字节序表示 }; // IPv6 struct sockaddr_in6 { sa_family_t sin6_family; // 地址族:AF_INET6 u_int16_t sin6_port; // 端口号,用网络字节序表示 u_int32_t sin6_flowinfo; // 流信息,应设置为0 struct in6_addr sin6_addr; // IPv6地址结构体 u_int32_t sin6_scope_id; // scope ID,尚处于实验阶段 }; struct in6_addr { unsigned char sa_addr[16]; // IPv6地址,用网络字节序表示 };
socket相关函数
-
socket函数 创建socket
#include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol);
- protofamily:协议族(family)。AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL、AF_UNIX等。
- type:指定socket类型。SOCK_STREAM(TCP)、SOCK_DGRAM(UDP)、SOCK_RAW、SOCK_PACKET等。与SOCK_NONBLOCK表示创建非阻塞socket,与SOCK_CLOEXEC表示fork创建的子进程中关闭该socket。
- protocol:指定协议。IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等。一般填 0 默认和type适配。
-
bind函数 绑定IP地址和端口号
#include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
-
sockfd: socket描述符
-
addr:前面的地址结构体
-
addrlen: 第二个参数中结构体的大小
-
-
listen函数 监听
#include <sys/socket.h> int listen(int sockfd, int backlog);
- sockfd: socket描述符
- backlog:全连接队列上限
-
connect函数 建立一个连接
#include <sys/types.h> #include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- sockfd: socket描述符
- addr:对端地址信息
- addrlen:addr的大小
-
accept函数 接受一个连接
#include <sys/types.h> #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- sockfd: socket描述符
- addr:对端地址信息
- addrlen:addr的大小
-
shutdown函数 关闭套接字的读或写端
#include <sys/socket.h> int shutdown(int sockfd,int how);
- sockfd: socket描述符
- how:SHUT_RD 断开输入流;SHUT_WR 断开输出流;SHUT_RDWR 同时断开 I/O 流
数据读写
-
recv和send用于TCP流数据读写
#include <sys/types.h> #include <sys/socket.h> ssize_t recv(int sockfd, void *buf, int len, int flags); ssize_t send(int sockfd, const void *buf, size_t len, int flags);
- sockfd: socket描述符
- buf:数据缓冲区
- len:buf大小
- flag:0 阻塞式发送;MSG_NOSIGNAL 当连接断开不产生SIGPIPE信号;MSG_DONTWAIT 非阻塞…
- 返回:实际发送或接收字节数;<0 出错;recv返回0表示连接断开
-
recvfrom和sendto用于UDP数据报读写
#include <sys/socket.h> ssize_t recvfrom(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *src_addr, socklen_t *addrlen); ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
- 相比recv和send多出的src_addr和dest_addr为对端的地址信息,addrlen指定其长度。当后两个参数都写NULL等同于recv和send的使用。
-
通用数据读写sendmsg和recvmsg
#include <sys/socket.h> ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); struct msghdr { void *msg_name; /* protocol address */ socklen_t msg_namelen; /* size of protocol address */ struct iovec *msg_iov; /* scatter/gatter array */ int msg_iovlen /* elements in msg_iov array */ void *msg_control; /* ancillary data (cmsghdr struct) */ socklen_t msg_controllen; /* length of ancillary data */ int msg_flags; /* flags returned by recvmsg */ }; struct iovec { ptr_t iov_base; /* Starting address */ size_t iov_len; /* Length in bytes */ };
- msg_name、msg_namelen:UDP传输时对端地址结构和其长度,TCP传输时置NULL
- msg_iov:输入或输出的缓冲区数组,其元素指定了分散的缓冲区的地址和长度,msg_iovlen成员指定了该数组大小
- msg_control和msg_controllen:辅助数据的位置和大小
- msg_flags:会复制flag的值,无须设定
获取地址信息
#include <sys/socket.h>
//获取本端socket地址
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
//获取对端socket地址
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
- 返回0代表成功,-1代表失败并设置errno
获取或者设置套接字属性
#include <sys/types.h>
#include <sys/socket.h>
int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);
-
sock:套接字描述符
-
level:选项所在的协议层。SOL_SOCKET、IPPROTO_IP、IPPROTO_IPV6、IPPROTO_TCP等
-
optname:需要设置或访问的选项名
-
optval:存放选项值的地址
-
optlen:选项值长度
-
optname:
选项名称 说明 数据类型 ======================================================================== SOL_SOCKET ------------------------------------------------------------------------ SO_BROADCAST 允许发送广播数据 int SO_DEBUG 允许调试 int SO_DONTROUTE 不查找路由 int SO_ERROR 获得套接字错误 int SO_KEEPALIVE 保持连接 int SO_LINGER 延迟关闭连接 struct linger SO_OOBINLINE 带外数据放入正常数据流 int SO_RCVBUF 接收缓冲区大小 int SO_SNDBUF 发送缓冲区大小 int SO_RCVLOWAT 接收缓冲区下限 int SO_SNDLOWAT 发送缓冲区下限 int SO_RCVTIMEO 接收超时 struct timeval SO_SNDTIMEO 发送超时 struct timeval SO_REUSERADDR 允许重用本地地址和端口 int SO_TYPE 获得套接字类型 int SO_BSDCOMPAT 与BSD系统兼容 int ======================================================================== IPPROTO_IP ------------------------------------------------------------------------ IP_HDRINCL 在数据包中包含IP首部 int IP_OPTINOS IP首部选项 int IP_TOS 服务类型 IP_TTL 生存时间 int ======================================================================== IPPRO_TCP ------------------------------------------------------------------------ TCP_MAXSEG TCP最大数据段的大小 int TCP_NODELAY 不使用Nagle算法 int ========================================================================
通过域名或地址获取主机信息
#include <netdb.h>
struct hostent *gethostbyname(const char *ghostname);
struct hostent * gethostbyaddr(const char *addr, size_t len , int family);
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* pointer to array of pointers to alias name */
int h_addrtype; /* host address type: AF_INET */
int h_length; /* length of address: 4 */
char **h_addr_list; /* ptr to array of ptrs with IPv4 addrs */
};
- h_name:主机规范名
- h_aliases:主机别名列表
- h_addrtype:主机ip地址类型
- h_length :主机ip地址列表长度
- h_addr_list:主机的ip地址列表(网络字节序)