1、主机字节序和网络字节序的转换
unsigned short int htons(unsigned short int hostshort);(比较常用的之一)
将短整型的主机字节序转换为网络字节序数据,htons是host to network short;
短整型一般用来转换端口号,长整型一般用来转换IP地址;
2、IP地址转换函数
in_addr_t inet_addr(const char* strptr);
将点分十进制字符串表示的IPV4地址转换为网络字节序整数表示的IPV4地址;
3、创建socket
int socket(int domain, int type, int protocol);
domain:协议族,AF_INET/PF_INET(TCP、IPV4协议族);
type:服务类型,SOCK_STREAM(TCP流服务)/ SOCK_DGRAM(UDP数据报);
protocol:具体协议,一般设置为0,表示使用默认协议;
4、命名socket
int bind(int sockfd, const struct sockaddr* my_addr, socklen_t addrlen);
将my_addr所指的socket地址分配给未命名的sockfd文件描述符,addrlen参数指出该socket地址的长度;
5、监听socket
int listen(int sockfd, int backlog);
backlog表示内核监听队列的最大长度(完全连接状态时socket的上限),典型值为5;
监听队列中完整连接的上限通常比backlog略大;
6、接收连接
int accept(int sockfd, struct sockaddr* addr, socket_t* addrlen);
sockfd是执行过listen系统调用的监听sockfd;
addr获取被接受连接的远端socket地址;
如果监听队列中处于ESTABLISHED状态的连接对应的客户端出现网络异常(比如掉线),或者提前退出,那么服务器对这个连接执行的accept调用是否成功?
答:accept只是从监听队列中取出连接,而不论连接处于何种状态,更不关心任何网络状况的变化。
7、发起连接
int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);
sockfd是由系统调用返回一个socket;
serv_addr是服务器监听的socket地址;
8、关闭连接
int close(int fd);
关闭连接是将fd的引用计数-1,当fd的引用计数为0,才真正断开连接;
多进程程序中,一次fork系统调用默认将使父进程中打开的socket的引用计数+1,因此我们必须在父进程和子进程中都对该socket执行close调用才能将连接关闭;
shutdown和close的区别:
shutdown能够分别关闭socket上的读或写,或者都关闭,
close在关闭连接时只能socket上读和写同时关闭。
扩展:
9、TCP数据读写
ssize_t 在32位系统上是unsigned int 无符号整型,在64位系统上是unsigned long无符号长整型;
size_t 一般用来表示一种计数,例如 sizeof返回的就是size_t类型;
(1)ssize_t recv(int sockfd, void* buf, size_t len, int flags);
recv读取sockfd上的数据;
buf和len分别指度缓冲区的位置和大小;
flags默认为0;
返回0:通信对方已关闭连接,返回-1:error;
(2)ssize_t send(int sockfd, const void* buf, size_t len, int flags);
send往sockfd上写入数据;
buf和len分别指写缓冲区的位置和大小;
成功返回实际写入的数据长度;
10、UDP数据读写
(1)ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t addrlen);
recvfrom读取sockfd上的数据;
buf和len分别指定度缓冲区的位置和大小;
src_addr:获取发送端的socket地址;
flags默认为0;
(2)ssize_t sendto(int sockfd, void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen);
sendto往sockfd上写入数据;
dest_addr指定接收端的socket地址;
recvfrom/sendto系统调用也可以用于面向连接(STREAM)的socket的数据读写,主需要把最后两个参数设置为NULL以忽略发送端/接收端的socket地址;