Linux高性能服务器编程:网络编程基础API

1. socket地址API

大端字节序:一个整数的高位字节存储在内存的低地址处,低位字节存储在内存的高地址处。

小端字节序:整数的高位字节存储在内存的高地址处,而低位字节则存储在内存的低地址处。

现代PC机采用小端字节序,又称为主机字节序。

大端字节序主要在网络上传输,称为网络字节序。

 

2. 创建socket

socket是可读、可写、可控制、可关闭的文件描述符。

int socket(int domain, int type, int protocol);

domain: 表示使用哪个底层协议族,对TCP/IP而言,该参数应该设置为PF_INET。

type: 表示服务类型,流服务:SOCK_STREAM, 数据报服务:SOCK_DGRAM。

protocol:0

 

3.命名socket

采用bind函数。

int bind(int sockfd, const struct sockaddr* my_addr, socklen_t addrlen);

bind将my_addr所指的socket地址分配给未命名的sockfd文件描述符,addrlen指出该socket地址的长度。

绑定失败时,返回-1,设置errno。

常见errno:

EACCES:被绑定的地址是受保护的地址。

EADDRINUSE:被绑定的地址在使用中,如将socket绑定到一个处于TIME_WAIT状态的socket地址。

 

4. 监听socket

int listen(int sockfd, int backlog);

sockfd指定被监听的socket。backlog提示内核监听队列的最大长度。监听队列长度超过backlog,服务器将不受理新的客户连接。典型值为5..

 

5.接受连接

int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);

sockfd是执行过listen系统调用的监听socket。addr参数用来获取被接受连接的远端socket地址,该socket

地址的长度由addrlen指出。accept成功时返回一个新的连接socket,该socket唯一地标识了

被接受的这个连接,服务器可通过读写该socket来与被接受连接的客户端通信。

accept只是从监听队列中取出连接,而不论连接处于何种状态,更不关心任何网络状况的变化。

 

6. 发起连接

int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);

connect成功时返回0,一旦成功建立连接,sockfd就唯一地标识了这个连接,客户端就可以通过读写sockfd来与服务器通信。

 

7.关闭连接

int close(int fd);

close将fd的引用计数减1,只有当fd的引用计数为0时,才真正关闭连接。多进程程序中,一次fork系统调用默认将使父进程中打开的socket的引用计数加1,

因此我们必须在父进程和子进程中都对socket执行close调用才能将连接关闭。

若要立即终止连接,可以使用:

int shutdown(int sockfd, int howto);

 

8. 数据读写

TCP读写:

ssize_t recv(int sockfd, void* buf, size_t len, int flags);

ssize_t send(int sockfd, const void* buf, size_t len, int flags);

recv读取sockfd上的数据,buf和len分别指定读缓冲区的位置和大小,falgs通常为0. recv成功时返回实际读取到的数据的长度。recv返回0,表示通信对方已经关闭连接。

send往sockfd上写入数据,buf和len分别指定写缓冲区的位置和大小。send成功时返回实际写入的数据的长度。

UDP读写:

ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags, 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);

recvfrom 读取sockfd上的数据,buf和len参数分别指定读缓冲区的位置和大小。每次读取数据时都需要获取发送端的socket地址。

sendto往sockfd上写入数据,buf和len分别指定写缓冲区的位置和大小。

recvfrom和sendto系统调用也可以用于面向连接的socket数据读写,只需要把最后两个参数都设置为NULL以忽略发送端/接收端的socket地址(因为已经建立了连接)。

通用数据读写:

ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags);

ssize_t sendmsg(itn sockfd, struct msghdr* msg, int flags);

可用于TCP流数据和UDP数据报。

 

9. 地址信息函数

int getsockname(int sockfd, struct sockaddr* address, socklen_t* address_len);  //获取sockfd对应的本端socket地址

int getpeername(int sockfd, struct sockaddr* address, socklen_t* address_len);  //获取sockfd对应的远端socket地址

 

通过设置socket选项SO_REUSEADDR来强制使用被处于TIME_WAIT状态的连接占用的socket地址。

 

posted @ 2020-02-27 14:23  c++11  阅读(254)  评论(0编辑  收藏  举报