Linux网络编程常用API 分类 创建socket 命名s

分类

Linux网络API可以分成三类

  1. socket地址API,socket指的是一个(ip,port)对,唯一地标记了TCP通信的一端。
  2. socket基础API,主要是指sys/socket.h头文件中,socket创建,命名,监听,接受连接,发起连接,读写数据,获取地址信息,检测带外标记,以及读取和设置socket选项。
  3. 网络信息API,实现主机名和IP地址之间的转换,以及服务名称和端口号之间的转换。

创建socket

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

  • domain指的是使用的协议簇,可选的有PF_INET(ipv4),PF_INET6(ipv6),PF_UNIX(unix)
  • type指的是服务类型,可以选数据报服务,数据流服务,更新后也可能传入非阻塞,和在fork时关闭socket的参数
  • protocol指的是协议,其实前两个参数已经能确定一个协议了。
  • 创建socket成功则返回一个文件描述符。

命名socket

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

  • 把my_addr指向的地址分配给文件描述符,addrlen参数指的是该socket地址的长度。
  • bind成功时返回0,失败返回-1并设置errno。其中两种常见的errno是EACCES和EADDRINUSE,它们的含义分别是地址被保护需要超级用户才能访问,绑定的地址正在使用中。

监听socket

int listen(int sockfd,int backlog)

  • sockfd指定被监听的socket
  • backlog指内核监听队列的最大长度,如果监听队列的长度超过该值,服务器将不受理新的客户连接,指定值是半连接长度+全连接长度的上限。
  • listen成功返回0,失败返回-1.

接受连接

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

  • 已经调用listen的socket
  • 远端的地址
  • socket地址的长度
  • accept成功时返回一个新的socket,服务器可通过读写该socket来与客户端进行通信。
  • 这里有一点,客户端握手成功后立马宕机,这时候服务端是无感知的。

发起连接

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

  • serv_addr是指服务端监听的地址
  • sockefd成功后返回一个socket,唯一地标识一个连接。
  • 可能会出现目标端口不存在或连接超时的可能。

关闭连接

int close(int fd)

  • fd指待关闭的连接,不是立马关闭一个连接,将fd的引用计数器减一,等到计数为0时才关闭连接。
  • 在fork进程时,系统调用会默认将父进程的socket的引用计数加1.

数据读写

TCP读写

1
2
c复制代码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参数分别指定读缓冲区的位置和大小
  • 成功时返回读取的数据长度

UDP读写

1
2
c复制代码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);
  • 由于UDP无连接,所以每一次都要获取发送端的地址。

高级IO函数

pipe()

int pipe(int fd[2])

  • pipe可以创建一个管道,以实现进程通信
  • 参数包含两个int型整数的数组指针。该函数成功时返回0,并将一对打开的文件描述符值填入数组中。
  • fd[0]和fd[1]分别构成管道的两端,使用的方向确定,不能反过来使用,如果想要实现双向通信,就应该使用两个管道。
  • 管道默认阻塞的。
  • 管道的默认大小为65535字节。

dup函数和dup2函数

1
2
c复制代码int dup(int file_descriptor)
int dup2(int file_descriptor_one,int file_descriptor_two)
  • 如果我们想把标准输入重定向到应该文件,或者把标准输出重定向到网络连接中,可以使用这两个函数
  • dup创建一个新的文件描述符,该新文件描述符和原有的文件描述符指向同一个文件,管道或网络连接,并且dup返回的文件描述符总是取系统当前可用的最小整数值,dup2返回第一个不小于file_descriptor_two的整数值。

readv函数和writev函数

分散读

集中写

sendfile

ssize_t sendfile(int out_fd,int in_fd,off_t *offset,size_t count)

  • 在两个文件描述符之间直接传递数据,避免了在内核缓冲区和用户缓冲区之间的数据拷贝,效率很高,被称为零拷贝。
  • in_fd必须指向一个真实文件,out_fd必须是一个socket

mmap函数和munmap函数

1
2
c复制代码void* mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset)
int munmap(void *start,size_t length);
  • mmap函数用于申请一段内存空间,我们可以将这段内存作为进程间通信的共享内存,也可以将文件直接映射到其中
  • munmap函数则释放由mmap创建的这段空间
  • start起始地址,可以由系统分配
  • prot指的是内存权限。

splice函数

ssize_t splice(int fd_in,loff_t* off_in,int fd_out,loff_t* off_out,size_t len,nusigned int flags)

  • 在两个文件描述符间移动数据,也就是零拷贝。

tee函数

ssize_t tee(int fd_in,int fd_out,size_t len,unsigned int flags)

  • 在两个管道间复制数据

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%