You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UDP IPv6客户端发送100MB文件失败,sendto调用报错求助

UDP IPv6 文件发送客户端问题排查与修复

核心问题分析

你的代码存在几个关键错误,直接导致发送失败:

  • 协议栈不匹配:代码使用AF_INET(IPv4协议族)和sockaddr_in(IPv4地址结构),但你需要实现的是UDP IPv6传输,两者完全不兼容。
  • 发送长度错误:sendto中用sizeof(data)作为发送长度,但fgets实际读取的字节数大概率小于SIZE,会把缓冲区空字符一并发送;若SIZE超过IPv6 UDP最大载荷(65507字节),会直接触发发送失败。
  • 文件打开未做校验:如果data.txt不存在或无法读取,fp会为NULL,后续fgets操作出错,间接引发sendto异常。
  • 目标地址配置错误:INADDR_ANY是IPv4通配地址,IPv6需使用in6addr_any或具体目标IPv6地址。
  • 无效标志位:MSG_CONFIRM是面向连接协议(如TCP)的标志,UDP使用该标志会引发未定义行为。

修复后的客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define P 8080
#define SIZE 65507  // IPv6 UDP最大载荷长度,避免超出发送限制

void client() {
    int sockfd;
    char buffer[65536];
    struct sockaddr_in6 servaddr;  // 使用IPv6地址结构

    // 创建IPv6 UDP套接字
    if ((sockfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    memset(&servaddr, 0, sizeof(servaddr));

    // 填充IPv6服务器信息
    servaddr.sin6_family = AF_INET6;
    servaddr.sin6_port = htons(P);
    // 替换为实际服务器IPv6地址,"::1"代表本地回环地址
    if (inet_pton(AF_INET6, "::1", &servaddr.sin6_addr) <= 0) {
        perror("invalid IPv6 address");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    int len = sizeof(servaddr);
    FILE *fp = fopen("data.txt", "rb");  // 二进制模式打开,避免文本格式转换问题
    if (!fp) {
        perror("failed to open file");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    char data[SIZE] = {0};
    ssize_t bytes_read;
    // 用fread获取实际读取字节数,精准发送有效数据
    while ((bytes_read = fread(data, 1, SIZE, fp)) > 0) {
        if (sendto(sockfd, data, bytes_read, 0, (const struct sockaddr *)&servaddr, len) == -1) {
            perror("[-]Error in sending file. in UDP CLIENT");
            fclose(fp);
            close(sockfd);
            exit(1);
        }
        memset(data, 0, SIZE);
    }

    if (ferror(fp)) {
        perror("error reading file");
        fclose(fp);
        close(sockfd);
        exit(1);
    }

    printf("File sent successfully.\n");

    // 接收服务器响应(按需保留)
    ssize_t n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&servaddr, &len);
    if (n > 0) {
        buffer[n] = '\0';
        printf("Server : %s\n", buffer);
    }

    fclose(fp);
    close(sockfd);
}

额外注意事项

  • UDP不可靠性:UDP是无连接、不可靠协议,传输100MB大文件时,需自行实现重传、校验、分片重组逻辑,否则会出现丢包、乱序导致文件损坏。
  • MTU适配:即使设置65507字节的载荷,实际网络MTU可能更小(如以太网MTU为1500字节),建议将分片大小设为MTU减去IPv6和UDP头部长度(例如1452字节),降低分片丢包概率。
  • 服务器端适配:服务器必须同步使用IPv6套接字(AF_INET6、sockaddr_in6)接收数据,否则无法建立通信。

内容的提问来源于stack exchange,提问作者ATB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:05:38