Loading

【Linux网络编程】Socket Api函数

【Linux网络编程】Socket Api函数

TCP/IP 协议族

TCP/IP 协议族有 sockaddr_insockaddr_in6 两个专用的 socket 地址结构体,它们分别用于 IPv4 和 IPv6,在此只将 IPv4,如下为 struct sockaddr_in

struct sockaddr_in {
    sa_family_t sin_family;   // 地址族:AF_INET
    u_int16_t sin_port;       // 端口号,要用网络字节序表示
    struct in_addr sin_addr;  // IPv4地址结构体,见下面
};

struct in_addr {
    u_int32_t s_addr;         // IPv4地址,需要用网络字节序表示
};

所有专用 socket 地址结构体如 sockaddr_in 类型的变量在实际使用时都需要转化为通用的 socket 地址类型 sockaddr(强制转换即可)。

创建 socket

socket 是一个可读、可写、可控制与可关闭的文件描述符。使用 socket 系统调用可创建一个 socket,在 #include <sys/types.h>#include <sys/socket.h> 中:

int socket(int domain, int type, int protocol);
  • domain:IP 地址类型,AF_INET 表示 IPv4,如果使用 IPv6 则是 AF_INET6。
  • type:数据传输方式,SOCK_STREAM 表示流服务,用于 TCP,SOCK_DGRAM 表示数据报,用于 UDP。
  • protocol:一般为 0,依据 type 自动推倒协议类型。

socket 系统调用成功时返回一个 socket 文件描述符,失败则返回 -1,并设置 errno。

命名 socket

在创建 socket 后,虽然指定了协议族,但是并未指定该协议族使用哪个具体的 socket 地址,由此将一个 socket 与 socket 地址绑定则称为给 socket 命名。命名 socket 的系统调用为 bind

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

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

bind 成功返回 0,失败则返回 -1 并设置 errno。

监听 socket

socket 被命名后,还不能马上接受客户的连接,需要使用 listen 的系统调用来创建一个监听队列以存放待处理的客户连接:

int listen(int sockfd, int backlog);

sockfd 表示指定被监听的 socket。backlog 参数提示内核监听队列的最大长度。而如果监听队列的长度超过 backlog,服务器将不再接受新的客户连接。建议 backlog 设置为 128。

listen 成功返回 0,失败返回 -1 并设置 errno。

接受连接

使用 accept 系统调用从 listen 监听队列中接受一个连接:

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

sockfd 是执行过 listen 系统调用的监听 socket。addr是一个新的 socket 地址,用来获取被接受连接的远端 socket 地址,该 socket 地址的长度有由 addrlen 指出。

accept成功时返回一个新的连接 socket,该 socket 唯一地标识了被接受的这个连接,服务器可通过读写该 socket 来与被接受连接对应的客户端通信。accept 失败时返回 -1 并设置 errno。

服务器:接受连接,客户端:被接受连接。

posted @ 2024-08-28 15:28  杨谖之  阅读(14)  评论(0编辑  收藏  举报