sockaddr_in
sockaddr_in是一个结构体,用于表示IPv4 地址和端口号的组合。在 C 语言中,它通常用于网络编程中的套接字操作,特别是在基于传输控制协议(TCP)和用户数据报协议(UDP)的网络通信中。
这个结构体在
头文件中定义,其结构如下:
struct sockaddr_in {
short sin_family; // 地址族(AF_INET),一般为 AF_INET
unsigned short sin_port; // 端口号,网络字节序
struct in_addr sin_addr; // IPv4 地址结构体
char sin_zero[8]; // 用于填充,使结构体和 sockaddr 结构体大小相同
};
sin_family
:地址族,通常为 AF_INET
,表示 IPv4 地址族。sin_port
:端口号,用于标识数据传输的目的地或来源端口,存储在网络字节序中(大端序)。
htons()
:将指定的端口号 port 转换为网络字节序(大端序)后,赋值给结构体的 sin_port
成员。htons()
函数用于将主机字节序的 16 位整数转换为网络字节序,以确保在网络上传输时的正确性。sin_addr
:一个 struct in_addr
类型的结构体,用于存储 IPv4 地址。htonl(INADDR_ANY);
:将 INADDR_ANY
赋值给结构体的 sin_addr.s_addr
成员。INADDR_ANY
表示接受来自任意网络接口的连接请求,即服务器将监听所有可用的网络接口。htonl()
函数用于将主机字节序的 32 位整数转换为网络字节序。sin_addr.s_addr
:初始化IP地址的方法有两种(如下),inet_pton()
直接把点分十进制格式的IP地址字符串转换成网络字节序的二进制形式,并存储到serverAddr.sin_addr
中,sin_addr.s_addr
是一个无符号整型变量(在netinet/in.h中定义),通常当你已经有了IP地址的数字表示时,可以直接赋值给它。然而,inet_addr()
函数不如inet_pton()
灵活,因为它不能处理IPv6
地址,并且对于非法的IPv4
地址字符串,它的错误处理不如inet_pton()
明确。serverAddr.sin_addr.s_addr = inet_addr("192.168.1.100");
`或`
inet_pton(AF_INET, serverIP, &serverAddr.sin_addr)
sin_zero
:填充字段,用于使 sockaddr_in
结构体和通用套接字地址结构体 sockaddr
大小相同。sockaddr_in
结构体的使用通常是在套接字编程中的地址初始化和绑定过程中。例如,通过这个结构体可以指定要连接到的远程服务器的地址和端口,或者指定要监听的本地地址和端口。socklen_t
socklen_t是一个数据类型,通常用于表示套接字地址结构体的长度。在 C 语言中,它通常是一个无符号整数类型,用于在套接字编程中传递地址结构体的大小信息。
在网络编程中,常见的套接字操作函数(如 bind()
、connect()
、accept()
等)通常需要传递一个指向地址结构体的指针以及该结构体的大小。socklen_t
类型的变量就用来存储这个大小。
socklen_t
的定义通常可以在
或
头文件中找到
typedef unsigned int socklen_t;
socket()
函数是在网络编程中常用的系统调用函数,用于创建一个新的套接字(socket)。套接字是一种通信机制,它允许不同计算机之间的进程进行通信,可以通过网络发送和接收数据。
在 C 语言中,socket()
函数的原型通常在头文件
中声明,其定义如下:
int socket(int domain, int type, int protocol);
domain
:指定套接字的协议族,常见的包括 AF_INET
(IPv4 地址族)和 AF_INET6
(IPv6 地址族)等。PF_INET
是套接字编程中常用的常量,用于指定套接字的协议族(Protocol Family)。在实际使用中,PF_INET
和 AF_INET
这两个常量通常是等价的,都表示使用 IPv4 地址族。
AF_INET
和 AF_INET6
,分别表示使用 IPv4 和 IPv6 地址族。而 PF_INET
和 PF_INET6
则是对应的协议族常量,它们与 AF_INET
和 AF_INET6
是一样的,用于指定套接字的地址族。AF
表示 Address Family,而 PF
则表示 ProtocolAF_INET
和 PF_INET
被交替使用。所以,当你需要指定使用 IPv4 地址族时,可以使用 AF_INET
或 PF_INET
,它们的效果是一样的type
:指定套接字的类型,常见的包括 SOCK_STREAM
(面向连接的流套接字,如 TCP)和 SOCK_DGRAM
(无连接的数据报套接字,如 UDP)等。protocol
:指定套接字使用的协议,通常设为 0,表示使用默认协议。socket()
函数返回一个非负整数作为套接字描述符(socket descriptor),如果返回 -1 则表示创建套接字失败。套接字描述符用于后续的套接字操作,比如绑定地址、连接到远程主机、接收和发送数据等。setsockopt()
setsockopt()
函数是用于设置套接字选项的系统调用函数之一。它允许你在套接字创建后,但在绑定或连接之前,设置各种套接字选项,以控制套接字的行为。
在 C 语言中,setsockopt()
函数的原型通常在
头文件中声明,其定义如下:
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
sockfd
:套接字描述符,即要设置选项的套接字。 level:选项级别,指定了要设置的选项的类型。常见的级别包括SOL_SOCKET
(通用套接字选项)、IPPROTO_TCP(TCP 协议选项)和 IPPROTO_IP(IP 协议选项)等。optname
:选项名称,指定了要设置的具体选项。 optval:指向包含选项值的缓冲区的指针。optlen
:选项值的长度,以字节为单位。setsockopt()
函数成功时返回 0,失败时返回 -1,并设置相应的错误码。常见的错误包括 EBADF
(无效的文件描述符)、EINVAL(无效的参数)和 ENOPROTOOPT
(协议不支持该选项)等。
常见的套接字选项包括:
SO_REUSEADDR
:允许套接字重新绑定到已使用的地址。SO_KEEPALIVE
:启用 TCP 连接的保持活动功能。SO_SNDBUF
和 SO_RCVBUF
:设置发送缓冲区和接收缓冲区的大小。bind()
bind()是一个系统调用函数,用于将套接字(socket)与地址(包括 IP 地址和端口号)关联起来。在网络编程中,通常在服务器端使用 bind()
函数将套接字绑定到特定的 IP 地址和端口号上,以便监听来自客户端的连接请求。
在 C 语言中,bind()
函数的原型通常在
头文件中声明,其定义如下:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
listen()
listen()
函数是用于将套接字设置为被动监听状态,以便接受客户端连接请求的系统调用函数之一。在服务器端套接字上调用 listen()
函数后,套接字将进入监听状态,开始等待客户端的连接请求,并将连接请求放入一个队列中等待处理。
int listen(int sockfd, int backlog);
listen()
函数成功时返回 0,失败时返回 -1,并设置相应的错误码。常见的错误包括 EBADF
(无效的文件描述符)、ENOTSOCK
(指定的文件描述符不是套接字)和 EOPNOTSUPP
(套接字不支持监听操作)等。
accept()
accept()
函数是在服务器端套接字上调用的系统调用函数之一,用于接受客户端的连接请求。它从处于监听状态的套接字的等待连接队列中取出一个连接请求,创建一个新的套接字,并返回新套接字的文件描述符,通过这个新的套接字可以与客户端进行通信。
在 C 语言中,accept() 函数的原型通常在
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd
:服务器端监听套接字的文件描述符,即要接受连接请求的套接字。addr
:指向一个结构体的指针,用于存储客户端的地址信息。如果不关心客户端的地址信息,可以传入 NULL。addrlen
:一个指向整数的指针,指向 addr
结构体的长度。在调用 accept()
函数之前,必须将其初始化为 sockaddr
结构体的大小。accept()
函数成功时返回一个新的文件描述符,代表了与客户端的连接。失败时返回 -1,并设置相应的错误码。常见的错误包括 EBADF
(无效的文件描述符)、EFAULT
(指针指向的地址不可访问)和 EINVAL
(无效的参数)等。