Linux高性能服务器编程(二)

5.网络编程api

5.1 主机字节序、网络字节序

字节序问题:
现代CPU的累加器一次能装载至少4个字节(32位机器),这4个字节在内存中排列的顺序将影响它被累加器装载成的整数的值。

  • 大端字节序:高位字节存储在内存的低位地址
  • 小端字节序:高位字节存储在内存的高位地址
大部分主机采用小端字节序,所以小端字节序又称为主机字节序。
大端字节序 == 网络字节序

端口的转换:

unsigned short int htons(unsigned short int hostshort);
unsigned short int ntohs(unsigned short int netshort);

IP地址转换:
点分十进制字符串表示的地址 <========>网络字节序整数表示的地址

int inet_aton(const char* ip, struct in_addr* inp);
int inet_pton(int af, const char* src, void* src);

char* inet_ntoa(struct in_addr in);
const char* inet_ntop(int af, const void* src, char* dst, socklen_t cnt);

在这里插入图片描述

5.2 创建socket

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

5.3 绑定地址

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

常见error

  • EACCES:被绑定的地址是受保护的,普通用户将socket绑定到知名服务器端口,bind将返回EACCES
  • EADDRINUSE:被绑定的地址在使用中

5.4 创建一个监听队列来存放待处理的客户连接

int listen(int sockfd, int backlog);

5.5 从监听对列中接受一个连接

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

监听队列中处于ESTABLISHED状态的连接对应的客户端出现网络异常(掉线)或提前退出,accept调用成功。accept只是从监听队列中取出连接,不论连接处于何种状态。

5.6 发起连接

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

常见errno:

  • ECONNREFUSED:目标端口不存在
  • ETIMEDOUT:连接超时

5.7 关闭连接

int close(int fd);

close系统调用并非总是立即关闭一个连接,而是将fd的引用计数-1。只有fd的引用计数==0时,才关闭连接。
多进程程序中,一次fork系统调用将使父进程打开的socket引用计数+1,必须在父、子进程中都对该socket执行close才能关闭连接。

int shutdown(int sockfd, int howto);

立即关闭socket。
在这里插入图片描述

5.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);

flags设为0
  • UDP
ssize_t recvfrom(int sockfd,  void *buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t *addrlen);
size_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen);

也可用于TCP,把后两个参数==NULL,因为已经建立连接,知道其地址
  • 通用数据读写
ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr* msg, int flags);

在这里插入图片描述

5.9 获取socket地址(本端、对端)

int getsockname(int sockfd, struct sockaddr* address, socklen_t* address_len);
int getpeername(int sockfd, struct sockaddr* address, socklen_t* address_len);

5.10 获取、设置socket选项

fcntl
int getsockopt(int sockfd, int level, int option_name, void* option_value);
int setsockopt(int sockfd, int level, int option_name, const void* option_value, socklen_t option_len);

SO_REUSEADDR
在这里插入图片描述

5.11 根据主机名(IP)获取主机的完整信息

struct hostent *gethostbyname(const char *name);

struct hostent *gethostbyname(const char *name);

struct hostent {
       char  *h_name;            /* official name of host */
       char **h_aliases;         /* alias list */
       int    h_addrtype;        /* host address type */
       int    h_length;          /* length of address */
       char **h_addr_list;       /* list of addresses */
}

5.12 根据名称(端口号)获取某个服务的完整信息

 struct servent *getservbyname(const char *name, const char *proto);
 struct servent *getservbyport(int port, const char *proto);

6. 高级I/O函数

6.1 pipe、socketpair

int pipe(int pipefd[2]);
  • 写端文件描述符pipefd[1]的引用计数减少到0,没有任何进程往管道里写数据,则read fd[0],返回0
  • 读端文件描述符pipefd[0]的引用计数减少到0,没有任何进程从管道里读数据,则write fd[1],返回SIGPIPE
//创建双向管道
int socketpair(int domain, int type, int protocol, int sv[2]);

domain:AF_UNIX

6.2 dup

int dup(int oldfd);
  • 复制文件描述符,新文件描述符和oldfd指向相同的文件、管道、socket
  • 通过dup复制的文件描述符并不继承原文件描述符的属性,如close-on-exec,non-blocking。
应用:CGI服务器

在这里插入图片描述

先关闭标准输出文件描述符STDOUT_FILENO(值==1),调用dup(),复制connfd文件描述符,dup总是使用系统最小的可用文件描述符(此时值==1),即标准输出指向connfd。服务器输出到标准输出的内容会直接被客户端获得。

6.3 fcntl

将一个文件描述符设置为非阻塞
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值