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

如何用C语言实现跨设备UDP通信?同设备正常跨设备失败求助

UDP跨设备通信问题排查

同一设备上运行UDP客户端和服务器代码时通信正常,但同一网络下不同设备运行时,客户端收不到服务器返回的消息。以下是服务器和客户端代码,求排查:

服务器代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h> 
#include <netinet/in.h>
#define BUFF_SIZE 1024
int main(int argc, char *argv[])
{
    int serv_socket,port_no,str_len;
    int opt = 1;
    socklen_t client_addr_size;
    struct hostent *hostp;
    char *hostaddrp;
    char buf[BUFF_SIZE];
    struct sockaddr_in server_addr, client_addr;

    if(argc < 2 )
    {
        fprintf(stderr,"Usage : %s <port> \n",argv[0]);
        exit(EXIT_FAILURE);
    }

    port_no = atoi(argv[1]);
    serv_socket = socket(PF_INET, SOCK_DGRAM, 0);
    if(serv_socket == -1)
    {
        perror("Error: opening socket()");
        exit(EXIT_FAILURE);
    }

    memset(&server_addr,0,sizeof(server_addr));
    memset(&client_addr,0,sizeof(client_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(atoi(argv[1]));

    if(setsockopt(serv_socket,SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) == -1)
    {
        perror("Error: setsockopt()");
        exit(EXIT_FAILURE);
    }
    if(bind(serv_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)
    {
        perror("bind() error");
    }

    
    while (1)
    {
        client_addr_size = sizeof(client_addr);
        str_len = recvfrom(serv_socket, buf, BUFF_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_size);
        hostp = gethostbyaddr((const char*)&client_addr.sin_addr.s_addr,sizeof(client_addr.sin_addr.s_addr), AF_INET);
        if(hostp == NULL)
        {
            perror("Error on gethostbyaddr");
        }
        hostaddrp = inet_ntoa(client_addr.sin_addr);
        if(hostaddrp == NULL)
        {
            perror("Error on inet_ntoa");
        }
        printf("server received datagram from %s <%s> \n",hostp->h_name,hostaddrp);
        sendto(serv_socket,buf,strlen(buf), 0,(struct sockaddr*)&client_addr,client_addr_size);

    }
    
    close(serv_socket);
    return 0 ;
}

客户端代码

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

void error_handling(char *message);
#define BUFF_SIZE 1024


char client_message[] = "88\n";
int main(int argc, char *argv[])
{
    int sock;
    char message[BUFF_SIZE];
    int str_len;
    socklen_t address_size;

    struct sockaddr_in serv_addr, from_addr;

    if(argc != 3)
    {
        printf("Usage :  <IP> <port> \n");
        exit(1);
    }
    printf("IP address : %s , port : %d \n",argv[1],atoi(argv[2]));

    sock = socket(PF_INET, SOCK_DGRAM, 0);
    if(sock == -1)
    {
        error_handling("socket() error !");
    }

    memset(&serv_addr,0,sizeof(serv_addr));
    
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]); //IP address
    serv_addr.sin_port = htons(atoi(argv[2]));

    while (1)
    {
        address_size = sizeof(from_addr);
        sendto(sock,client_message,strlen(client_message),MSG_CONFIRM,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
        str_len = recvfrom(sock,message,BUFF_SIZE,MSG_WAITALL,(struct sockaddr*)&from_addr,&address_size);
        message[str_len] = 0;
        printf("Received message from server : %s \n",message);
        sleep(5);
    }
    close(sock);
    return 0;
}


void error_handling(char *message)
{ 
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

排查方向

  • 防火墙/安全组限制:检查服务器和客户端设备的防火墙,确保UDP目标端口(服务器监听端口)已开放,允许双向通信。
  • 网络地址问题:
    • 客户端连接时使用的服务器IP必须是服务器在当前局域网内的真实IP(不是127.0.0.1),可通过ifconfig(Linux)或ipconfig(Windows)确认。
    • 服务器绑定的INADDR_ANY没问题,会监听所有网卡的请求。
  • 代码潜在问题:
    • 服务器端sendto使用strlen(buf),但recvfrom返回的str_len才是实际接收的字节数,若客户端发送的消息不含终止符,strlen(buf)可能出错,建议改为sendto(serv_socket, buf, str_len, 0, ...)。
    • 客户端使用MSG_WAITALL标志,UDP是无连接协议,该标志可能导致recvfrom阻塞等待完整数据,建议去掉此标志,使用默认0即可。
    • 检查inet_addr的返回值,若客户端输入的IP格式错误,inet_addr会返回INADDR_NONE,需要添加错误处理。
  • 网络路由问题:确认两台设备在同一子网,可通过互相ping对方IP验证连通性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:27:54