要实现支持IPv4和IPv6协议的服务端,可以使用socket编程来完成。以下是一个简单的C++代码示例:
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8080
int main(int argc, char *argv[]) {
int server_fd, new_socket;
struct sockaddr_in6 address;
int opt = 1;
int addrlen = sizeof(address);
// 创建socket
if ((server_fd = socket(AF_INET6, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置socket选项,允许地址重用
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
// 设置地址族为IPv6
address.sin6_family = AF_INET6;
// 设置监听的端口号
address.sin6_port = htons(PORT);
// 将IP地址设置为任意地址
address.sin6_addr = in6addr_any;
// 绑定到指定的IP地址和端口上
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 开始监听客户端连接请求
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
std::cout << "Server started and listening on port " << PORT << std::endl;
while (true) {
// 接受客户端连接请求
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 打印客户端的地址信息
char ip[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &address.sin6_addr, ip, INET6_ADDRSTRLEN);
std::cout << "New client connected from " << ip << std::endl;
// TODO: 处理客户端请求
}
return 0;
}
在客户端连接时,可以使用getaddrinfo()
函数来自动判断是IPv4还是IPv6地址。以下是一个简单的C++代码示例:
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define PORT 8080
int main(int argc, char *argv[]) {
int sock = 0;
struct sockaddr_in6 serv_addr;
// 解析主机名和服务名,获取对应的IP地址和端口号列表
struct addrinfo hints{};
hints.ai_family = AF_UNSPEC; // 支持IPv4和IPv6
hints.ai_socktype = SOCK_STREAM; // 使用TCP协议
struct addrinfo *result;
if (getaddrinfo(argv[1], argv[2], &hints, &result) != 0) {
perror("getaddrinfo");
exit(EXIT_FAILURE);
}
// 尝试连接到服务器,直到成功或出错为止
for (struct addrinfo *rp = result; rp != nullptr; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock == -1) {
continue;
}
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) {
break;
}
close(sock);
}
// 如果连接失败,则输出错误信息并退出
if (sock == -1) {
perror("connect");
exit(EXIT_FAILURE);
}
// 打印连接成功的服务器地址信息
char ip[INET6_ADDRSTRLEN];
inet_ntop(serv_addr.sin6_family, &serv_addr.sin6_addr, ip, INET6_ADDRSTRLEN);
std::cout << "Connected to " << ip << ":" << ntohs(serv_addr.sin6_port)
<< std::endl;
// TODO: 发送和接收数据
return 0;
}
以上代码示例只是一个简单的演示,实际上在处理客户端请求时还需要进行更多的工作。例如,可以使用select()
函数来实现非阻塞IO,使用线程或者进程来处理多个客户端请求等等。
内容由零声教学AI助手提供,问题来源于学员提问