TCP/IP网络通信(C++语言)

套接字

创建套接字

设置套接字地址结构

sockaddr_in

sockaddr_in是一个结构体,用于表示IPv4 地址和端口号的组合。在 C 语言中,它通常用于网络编程中的套接字操作,特别是在基于传输控制协议(TCP)和用户数据报协议(UDP)的网络通信中。
这个结构体在 <netinet/in.h> 头文件中定义,其结构如下:

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 的定义通常可以在 <sys/socket.h><netinet/in.h> 头文件中找到

typedef unsigned int socklen_t;
socket()

函数是在网络编程中常用的系统调用函数,用于创建一个新的套接字(socket)。套接字是一种通信机制,它允许不同计算机之间的进程进行通信,可以通过网络发送和接收数据。

在 C 语言中,socket() 函数的原型通常在头文件 <sys/socket.h> 中声明,其定义如下:

int socket(int domain, int type, int protocol);
  • domain:指定套接字的协议族,常见的包括 AF_INET(IPv4 地址族)和 AF_INET6(IPv6 地址族)等。
  • PF_INET 是套接字编程中常用的常量,用于指定套接字的协议族(Protocol Family)。在实际使用中,PF_INETAF_INET 这两个常量通常是等价的,都表示使用 IPv4 地址族。
    • 在套接字编程中,有两种常见的协议族常量:AF_INETAF_INET6,分别表示使用 IPv4 和 IPv6 地址族。而 PF_INETPF_INET6 则是对应的协议族常量,它们与 AF_INETAF_INET6 是一样的,用于指定套接字的地址族。
    • AF 表示 Address Family,而 PF 则表示 Protocol
      Family,实际上,它们在大多数情况下是等价的。在一些文档和实现中,你可能会看到 AF_INETPF_INET 被交替使用。所以,当你需要指定使用 IPv4 地址族时,可以使用 AF_INETPF_INET,它们的效果是一样的
  • type:指定套接字的类型,常见的包括 SOCK_STREAM(面向连接的流套接字,如 TCP)和 SOCK_DGRAM(无连接的数据报套接字,如 UDP)等。
  • protocol:指定套接字使用的协议,通常设为 0,表示使用默认协议。
    socket() 函数返回一个非负整数作为套接字描述符(socket descriptor),如果返回 -1 则表示创建套接字失败。套接字描述符用于后续的套接字操作,比如绑定地址、连接到远程主机、接收和发送数据等。
setsockopt()

setsockopt()函数是用于设置套接字选项的系统调用函数之一。它允许你在套接字创建后,但在绑定或连接之前,设置各种套接字选项,以控制套接字的行为。

在 C 语言中,setsockopt() 函数的原型通常在<sys/socket.h>头文件中声明,其定义如下:

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() 函数的原型通常在 <sys/socket.h> 头文件中声明,其定义如下:

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

(服务器端)监听连接

listen()

listen() 函数是用于将套接字设置为被动监听状态,以便接受客户端连接请求的系统调用函数之一。在服务器端套接字上调用 listen() 函数后,套接字将进入监听状态,开始等待客户端的连接请求,并将连接请求放入一个队列中等待处理。

int listen(int sockfd, int backlog);
  • sockfd:套接字描述符,即要设置为监听状态的套接字。
  • backlog:连接请求的最大排队数,即等待处理的连接请求的最大数量。如果队列已满,则新的连接请求将被拒绝。通常情况下,这个参数的合理值为
    5 到 10。

listen() 函数成功时返回 0,失败时返回 -1,并设置相应的错误码。常见的错误包括 EBADF(无效的文件描述符)、ENOTSOCK(指定的文件描述符不是套接字)和 EOPNOTSUPP(套接字不支持监听操作)等。

接受连接(服务器端)

accept()

accept()函数是在服务器端套接字上调用的系统调用函数之一,用于接受客户端的连接请求。它从处于监听状态的套接字的等待连接队列中取出一个连接请求,创建一个新的套接字,并返回新套接字的文件描述符,通过这个新的套接字可以与客户端进行通信。

在 C 语言中,accept() 函数的原型通常在 <sys/socket.h> 头文件中声明,其定义如下:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • sockfd:服务器端监听套接字的文件描述符,即要接受连接请求的套接字。
  • addr:指向一个结构体的指针,用于存储客户端的地址信息。如果不关心客户端的地址信息,可以传入 NULL。
  • addrlen:一个指向整数的指针,指向 addr 结构体的长度。在调用 accept() 函数之前,必须将其初始化为 sockaddr 结构体的大小。

accept() 函数成功时返回一个新的文件描述符,代表了与客户端的连接。失败时返回 -1,并设置相应的错误码。常见的错误包括 EBADF(无效的文件描述符)、EFAULT(指针指向的地址不可访问)和 EINVAL(无效的参数)等。

连接到服务器(客户端)

发送和接收数据

关闭套接字

未完待续…

  • 50
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值