基本TCP套接字操作

include <sys/types.h> /* See NOTES */

include <sys/socket.h>

基本TCP客户-服务器程序套接字函数.png

socket

创建一个套接字,指定通信协议类型

// 成功:返回文件描述符	失败:返回-1,设置errno
int socket(int domain, int type, int protocol);
  • domain :协议族

    AF_INETAF_INET6、AF_LOCAL、AF_ROUTE、AF_KEY

    AF_XXX地址族PF_XXX 指协议族。但是在实际中,支持多个地址族的协议族从来没有实现过,且<sys/socket.h>中 PF_ 值总是与对应的 AF_ 值相等,因此,两者值相等,现在可看成是一个意思

  • type :套接字类型

    SOCK_STREAMSOCK_DGRAM、SOCK_SEQPACKET、SOCK_RAW

  • protocol :某协议类型的常值,通常为0

domain-type组合.png

bind

把一个本地协议地址赋予一个套接字。

协议地址:ip地址 + port

// 成功:返回0	失败:返回-1,设置errno(常见:EACCES、EADDRINUSE)
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

struct sockaddr_in {
   sa_family_t    sin_family; /* address family: AF_INET */
   in_port_t      sin_port;   /* port in network byte order */
   struct in_addr sin_addr;   /* internet address */
};

/* Internet address. */
struct in_addr {
   uint32_t       s_addr;     /* address in network byte order */
};
  • sockfd :文件描述符(套接字)
  • addr:指向特定协议的地址结构的指针
  • addrlen :地址结构长度

listen

做两件事:

  1. 把一个未连接的主动套接字转换成被动套接字,指示内核接收指向该套接字的连接请求,CLOSED状态 --> LISTEN状态
  2. backlog规定已完成连接队列的最大连接个数
// 成功:返回0	失败:返回-1,设置errno
int listen(int sockfd, int backlog);

内核为任何一个给定的监听套接字维护两个队列:

  • 未完成连接队列:正在等待完成TCP三次握手,处于 SYN_RCVD 状态
  • 已完成连接队列:已完成TCP三次握手,等待通过 accept 从队列中取出已连接套接字,处于 ESTABLISED 状态

Linux 2.2 以后,backlog 表示已完成连接队列的 socket 上限。实际测试中,队列最大长度为 backlog + 1

测试代码及数据listen()函数backlog参数测试

connect

TCP客户端使用,用于建立与TCP服务器的连接

// 成功:返回0	失败:返回-1,设置errno
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

accept

有TCP服务器调用,从已完成连接队列队头返回一个描述符。若队列为空,进程睡眠(默认阻塞方式)

// 成功:返回非负描述符	失败:返回-1,设置errno
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

若对返回客户端协议地址不感兴趣,可把 addr、addrlen 均值为空指针。

close

关闭套接字,该套接字不能再被调用进程使用。并发服务器中,close调用实际是相应套接字引用计数减1

// 成功:返回0	失败:返回-1,设置errno
int close(int sockfd);

当close关闭套接字时,TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后的是正常的TCP连接终止序列(四次握手)。

posted @ 2021-01-25 14:34  JakeLin  阅读(71)  评论(0编辑  收藏  举报