初识linux网络编程的Posix API与网络协议栈

一:Posix API是什么

        POSIX,全称为“可移植操作系统接口”(Portable Operating System Interface),最初由IEEE组织制定,目的是为了使不同的操作系统之间可以互相兼容。POSIX标准定义了一系列API和命令行工具,规定了操作系统应该提供哪些功能,以及这些功能的调用方式和行为。这些标准都是为了让不同的操作系统之间具有更好的兼容性,以便更方便地编写跨平台程序。

        对于Posix API,这里做了详细介绍一文带你彻底搞懂posix - 知乎

二:网络编程中的Posix API

客户端服务端
1:socket()1:socket()epoll_create()
2:bind()2:bind()epoll_ctl()
3:listent()epoll_wait()
3:connect()4:accept()
4:send()5:recv()
5:recv()6:send()
6:close()7:close()
  •  关于socket

//函数原型 
int socket(int domain, int type, int protocol);

               socket,中文翻译为插座,表示一一对应的一个关系;程序调用socket时,会分配一个fd,同时根据传入的网络协议、通信方式创建对应的TCB(TCP control block)\UDPCB(udp control block),创建的控制块包含TCP\UDP协议的所有状态信息和控制信息,如源IP地址、源端口、目的IP地址、目的端口、传输层协议、序列号、确认号、窗口大小、拥塞控制等。这些信息将用于实现TCP协议的行为和进行网络通信的控制。

  • 关于bind

//函数原型
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

             bind函数与tcp协议无关,该函数在与将传入的网络参数和fd对应的控制块绑定;简单来讲相当于一个set设置过程,bind根据传入的fd找到与之对应的控制块,而后将五元组(源IP地址、源端口、目的IP地址、目的端口、传输层协议)信息设置到对应的控制块中。

        在客户端,如果没有进行bind处理,程序会默认使用0.0.0.0基任意ip地址都可以作为源地址,同时分配一个任意port端口,此端口值在我们设置的设置的范围中。

//sysctl.conf文件中添加以下命令,控制端口范围
net.ipv4.ip_local_port_range = <起始端口号> <结束端口号>
  • 关于listen,3次握手建立连接

//函数原型
 int listen(int sockfd, int backlog);

         backlog参数理解:(避免syn泛洪)

        1:syn半连接队列的长度;(避免syn泛洪、dos攻击,但变的鸡肋(堡垒机等存在),当前在接收数据之前会做隔离,不用在考虑syn泛洪问题)

                根据下图TCP三次握手,此时考虑的是大量conect连接介入,而不做后续处理,此时会导致大量节点堆积在syn队列中(syn泛洪);

        2:syn+accept队列总长度,未被分配fd的tcb的数量;

                若accept队列中不做处理,会造成大量连接堆积,此时可以避免此种情况发生。

        3:描述accept全连接队列长度。

        listen函数功能:

                1:将tcb(tcp控制块)中的状态修改为TCP_STATUS_LISTEN;

                2:分配一个syn(半连接)队列;

                3:分配一个accept(全连接)队列。

acknum=syn seqnum+1,表示在acknum之前的所有数据都接收到了。

        当客户端有链接过来时,会将传过来的tcb控制块作为节点存放到syn队列当中,当经过accept建立完连接之后会根据tcp五元组信匹配到syn队列中的tcb移动到accept队列当中,而后调用accept将节点从全连接队列中移除。

  • 关于connect

//函数原型
 int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);

        connect函数就是发起连接请求,内核接收到请求会建立tcp3次握手连接。 

  • 关于send、recv

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

         通过参数sockfd找到特定的网络通道进行数据接收和发送

        如上图所示,send函数将数据从用户端拷贝到内核中,内核中何时发送数据应用层无法控制;在应用层调用3次send,可能在内核中会将这3次的数据作为一个数据包发送;

        同理,recv也只是将数据从内核中拷贝到应用层。

  • 关于accept

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

   1:调用accept之后,内核会根据传入的tcp五原则(ip信息参数)取出accept全连接队列中与之相匹配的节点。

    2:从全连接队列中取出一个节点后,内核会为这个节点创建一个socket,这个新的套接字就是服务器和指定客户端的专属通道;

   3:为新创建的套接字返回一个fd文件描述符。

  • 关于close,四次挥手结束链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值