C++的UDP连接解析域名地址错误

背景

使用c++开发一个udp连接功能的脚本,可以接收发送数据,而且地址是经过内网穿透到外网的

经过

通常发送数据给目标地址,需要把目的地址结构化,要么使用inet_addr解析ip地址,要么使用inet_pton

cpp 复制代码
sockaddr_in target_addr{};
target_addr.sin_family = AF_INET;
target_addr.sin_addr.s_addr = inet_addr("192.168.x.xxx");
target_addr.sin_port = htons(TARGET_PORT);
cpp 复制代码
sockaddr_in target_addr{};
target_addr.sin_family = AF_INET;
if (inet_pton(AF_INET, "192.168.x.xxx", &target_addr.sin_addr) <= 0) {
        std::cerr << "Invalid target address" << std::endl;
        close(server_socket);
        close(client_socket);
        return 1;
    }
target_addr.sin_port = htons(TARGET_PORT);

正常的ip地址是可以的,但是如果是个域名(例如server.natappfree.cc),就会报错
Failed to send data
Invalid target address

原因

inet_pton 函数主要用于将点分十进制的 IPv4 地址或 IPv6 地址字符串转换为二进制形式,它只能处理 IP 地址,不能直接处理域名(如 server.natappfree.cc)。当你传入域名时,它会因为无法识别该字符串为有效的 IP 地址格式而报错 Invalid target address。

要解决这个问题,

你需要使用 DNS 解析将域名转换为对应的 IP 地址。

在 C++ 中,可以使用 getaddrinfo 函数来完成这个任务

(如果你用python,是可以直接写域名的)

示例

cpp 复制代码
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <thread>
#include <errno.h>
#include <netdb.h>

#define SERVER_PORT 1001
#define TARGET_PORT 1002
#define BUFFER_SIZE 1024

int main() {
    // 创建服务器套接字
    int server_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if (server_socket == -1) {
        std::cerr << "Failed to create server socket" << std::endl;
        return 1;
    }

    // 绑定服务器地址
    sockaddr_in server_addr{};
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(SERVER_PORT);

    if (bind(server_socket, reinterpret_cast<sockaddr*>(&server_addr), sizeof(server_addr)) == -1) {
        std::cerr << "Failed to bind server socket" << std::endl;
        close(server_socket);
        return 1;
    }

    std::cout << "Listening on " << inet_ntoa(server_addr.sin_addr) << ":" << ntohs(server_addr.sin_port) << std::endl;

    // 创建客户端套接字
    int client_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if (client_socket == -1) {
        std::cerr << "Failed to create client socket" << std::endl;
        close(server_socket);
        return 1;
    }

    // 目标地址
    addrinfo hints{};
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;

    addrinfo* result;
    int status = getaddrinfo("server.natappfree.cc", std::to_string(TARGET_PORT).c_str(), &hints, &result);
    if (status != 0) {
        std::cerr << "getaddrinfo failed: " << gai_strerror(status) << std::endl;
        close(server_socket);
        close(client_socket);
        return 1;
    }

    sockaddr_in* target_addr = reinterpret_cast<sockaddr_in*>(result->ai_addr);

    const char* message = "i am udp";
    int i = 10;

    while (i > 0) {
        char buffer[BUFFER_SIZE];
        sockaddr_in client_addr{};
        socklen_t client_addr_len = sizeof(client_addr);

        // 接收数据
        ssize_t recv_len = recvfrom(server_socket, buffer, BUFFER_SIZE, 0, reinterpret_cast<sockaddr*>(&client_addr), &client_addr_len);
        if (recv_len == -1) {
            std::cerr << "Failed to receive data" << std::endl;
            continue;
        }

        buffer[recv_len] = '\0';
        std::cout << "recv " << buffer << " from " << inet_ntoa(client_addr.sin_addr) << ":" << ntohs(client_addr.sin_port) << std::endl;

        // 发送数据
        ssize_t send_len = sendto(client_socket, message, strlen(message), 0, reinterpret_cast<sockaddr*>(target_addr), sizeof(*target_addr));
        if (send_len == -1) {
            std::cerr << "Failed to send data: " << strerror(errno) << std::endl;
        }

        std::this_thread::sleep_for(std::chrono::seconds(1));
        i--;
    }

    // 释放地址信息
    freeaddrinfo(result);

    // 关闭套接字
    close(server_socket);
    close(client_socket);

    return 0;
}
相关推荐
lbb 小魔仙几秒前
【Python】零基础学 Python 爬虫:从原理到反爬,构建企业级爬虫系统
开发语言·爬虫·python
Swift社区2 分钟前
ArkTS Web 组件里,如何通过 javaScriptProxy 让 JS 同步调用原生方法
开发语言·前端·javascript
Q741_1473 分钟前
海致星图招聘 数据库内核研发实习生 一轮笔试 总结复盘(1) 作答语言:C/C++ 链表 二叉树
开发语言·c++·经验分享·面试·笔试
咔咔咔的6 分钟前
1970. 你能穿过矩阵的最后一天
c++
秃了也弱了。7 分钟前
FASTJSON库:阿里出品java界json解析库,使用与踩坑记录
java·开发语言·json
_OP_CHEN7 分钟前
【从零开始的Qt开发指南】(十九)Qt 文件操作:从 I/O 设备到文件信息,一站式掌握跨平台文件处理
开发语言·c++·qt·前端开发·文件操作·gui开发·qt文件
CSDN_RTKLIB8 分钟前
【std::map】双向迭代器说明
c++·stl
王老师青少年编程12 分钟前
信奥赛C++提高组csp-s之欧拉回路
c++·算法·csp·欧拉回路·信奥赛·csp-s·提高组
No0d1es14 分钟前
2025年12月 GESP CCF编程能力等级认证C++六级真题
c++·青少年编程·gesp·ccf·6级
Terrence Shen19 分钟前
【CUDA编程系列】之01
c++·人工智能·深度学习·机器学习