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

UDP INET Socket通信异常:客户端recvfrom阻塞无响应

问题排查:UDP客户端卡在recvfrom无法接收服务端回复

我在实现UDP INET Socket通信时,客户端能成功向服务端发送消息,服务端也能收到,但服务端回复后,客户端终端没有输出,程序卡在recvfrom调用处。请帮忙排查问题。

服务端代码

int main()
{
    int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in adres;

    adres.sin_addr.s_addr = INADDR_ANY;
    adres.sin_port = htons(2001);
    adres.sin_family = AF_INET;

    int bind_socket = bind(udp_socket, (struct sockaddr*) &adres, sizeof(adres));
    if (bind_socket == -1)
    {
        perror("Bind");
        return 0;
    }
    char msg[50];
    char msg1[50];
    strcpy(msg1, "Sending to client!");

    int rcv = recvfrom(udp_socket, msg, sizeof(msg), 0, (struct sockaddr *)&adres, (socklen_t *)sizeof(adres));
    int sending = sendto(udp_socket, msg1, sizeof(msg1), 0, (struct sockaddr *)&adres, sizeof(adres));
    close(udp_socket);

    return 0;
}

客户端代码

int main()
{       
    int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if(udp_socket < 0) {
        perror("Socket");
    }
    struct sockaddr_in adres;
    adres.sin_addr.s_addr = INADDR_ANY;
    adres.sin_port = htons(2001);
    adres.sin_family = AF_INET;
    char msg[50];
    strcpy(msg, "Sending to server!");
    int sendx = sendto(udp_socket, msg, 50, 0, (struct sockaddr*) &adres, sizeof(adres));
    char rcvmsg[50];
    int rcv = recvfrom(udp_socket, rcvmsg, 50, 0, (struct sockaddr*) &adres, (socklen_t*) sizeof(adres)); 
    printf("%s:\n", rcvmsg);
    close(udp_socket);

    return 0;
}

问题分析与解决方案

核心问题

服务端recvfrom的最后一个参数传递错误:recvfrom要求传入指向socklen_t变量的指针,用来存储发送方地址的实际长度。你直接传了(socklen_t *)sizeof(adres),这相当于把一个整数的地址强转过去,会导致adres的内容被破坏,服务端回复时用的是错误的客户端地址,所以客户端永远收不到回复,卡在recvfrom。

其他问题及修正

  1. 服务端

    • 新增socklen_t addr_len = sizeof(adres);,将&addr_len作为recvfrom的最后一个参数。
    • 检查recvfrom和sendto的返回值,及时处理错误。
    • 给接收的字符串添加结束符,避免乱码。
    • sendto时用strlen(msg1)代替sizeof(msg1),减少不必要的字节发送。
  2. 客户端

    • 将adres.sin_addr.s_addr改为服务端的实际IP(比如本地测试用inet_addr("127.0.0.1")),INADDR_ANY不适合作为客户端的目标地址。
    • 同样检查sendto和recvfrom的返回值。
    • 给接收的字符串添加结束符,修正printf的格式。

修正后的代码

服务端

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

int main()
{
    int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if (udp_socket == -1) {
        perror("socket");
        return 1;
    }

    struct sockaddr_in adres;
    memset(&adres, 0, sizeof(adres));
    adres.sin_addr.s_addr = INADDR_ANY;
    adres.sin_port = htons(2001);
    adres.sin_family = AF_INET;

    int bind_socket = bind(udp_socket, (struct sockaddr*) &adres, sizeof(adres));
    if (bind_socket == -1)
    {
        perror("Bind");
        close(udp_socket);
        return 1;
    }

    char msg[50];
    char msg1[50] = "Sending to client!";
    socklen_t addr_len = sizeof(adres);

    int rcv = recvfrom(udp_socket, msg, sizeof(msg)-1, 0, (struct sockaddr *)&adres, &addr_len);
    if (rcv == -1) {
        perror("recvfrom");
        close(udp_socket);
        return 1;
    }
    msg[rcv] = '\0';
    printf("Received from client: %s\n", msg);

    int sending = sendto(udp_socket, msg1, strlen(msg1), 0, (struct sockaddr *)&adres, addr_len);
    if (sending == -1) {
        perror("sendto");
        close(udp_socket);
        return 1;
    }

    close(udp_socket);
    return 0;
}

客户端

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

int main()
{       
    int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if(udp_socket == -1) {
        perror("Socket");
        return 1;
    }

    struct sockaddr_in adres;
    memset(&adres, 0, sizeof(adres));
    adres.sin_addr.s_addr = inet_addr("127.0.0.1");
    adres.sin_port = htons(2001);
    adres.sin_family = AF_INET;

    char msg[50] = "Sending to server!";
    int sendx = sendto(udp_socket, msg, strlen(msg), 0, (struct sockaddr*) &adres, sizeof(adres));
    if (sendx == -1) {
        perror("sendto");
        close(udp_socket);
        return 1;
    }

    char rcvmsg[50];
    socklen_t addr_len = sizeof(adres);
    int rcv = recvfrom(udp_socket, rcvmsg, sizeof(rcvmsg)-1, 0, (struct sockaddr*) &adres, &addr_len); 
    if (rcv == -1) {
        perror("recvfrom");
        close(udp_socket);
        return 1;
    }
    rcvmsg[rcv] = '\0';
    printf("Received from server: %s\n", rcvmsg);

    close(udp_socket);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:05:24