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

M1 Mac运行C客户端服务器程序遇nodename解析错误求助

问题描述

我用C语言开发了客户端与服务器程序(代码经教授审核确认无误),但在搭载M1芯片的Mac上执行以下命令时:

./client server 50000

(指定主机名server和端口50000),弹出错误提示:

名称解析错误:未提供节点名或服务名,或无法识别

我完全不清楚问题成因,以下是服务器端和客户端的C代码:

服务器端代码
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>

#define BUFSIZE 4096

const char *service = "50000";

// 处理子进程退出信号
void handler(int sign){
    int status;
    (void)sign;
    while(waitpid(-1, &status, WNOHANG) > 0){
        continue;
    }
}

int main(){
    int cc, err, on, sd;
    struct addrinfo hints, *res;
    struct sigaction sa;

    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sa.sa_handler = handler;

    if(sigaction(SIGCHLD, &sa, NULL) == -1){
        perror("sigaction调用失败");
        exit(EXIT_FAILURE);
    }

    memset(&hints,0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    // 此处存在错误:第一个参数不应传入stderr
    err = getaddrinfo(stderr,service, &hints, &res);
    if(err != 0){
        fprintf(stderr,"getaddrinfo错误:%s\n",gai_strerror(err));
        exit(EXIT_FAILURE);
    }

    sd = socket(res->ai_family, res->ai_socktype,res->ai_protocol);
    if(sd < 0){
        perror("创建套接字失败");
        exit(EXIT_FAILURE);
    }

    on = 1;
    if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,&on, sizeof(on)) < 0){
        perror("设置套接字选项失败");
        exit(EXIT_FAILURE);
    }

    cc = bind(sd, res->ai_addr, res->ai_addrlen);
    if(cc < 0){
        perror("绑定套接字失败");
        exit(EXIT_FAILURE);
    }
    
    cc = listen(sd, SOMAXCONN);
    if(cc < 0){
        perror("监听套接字失败");
        exit(EXIT_FAILURE);
    }

    for(;;){
        int pid, ns;

        ns = accept(sd, NULL, NULL);
        if(ns < 0){
            if(errno == EINTR){
                continue;
            }
            perror("接受连接失败");
            exit(EXIT_FAILURE);
        }

        pid = fork();
        if(pid < 0){
            perror("创建子进程失败");
            exit(EXIT_FAILURE);
        }else if (pid == 0){
            /*子进程*/
            char year[BUFSIZE];
            char number[BUFSIZE];
            char type[BUFSIZE];
            const char *ack = "ACK\n";
            int pid_n1, pid_n2;
            int pipe_n1n2[2], pipe_n2f[2];

            close(sd);

            memset(year, 0, sizeof(year));
            cc = read(ns, year, sizeof(year) - 1);
            if(cc < 0){
                perror("读取数据失败");
                exit(EXIT_FAILURE);
            }

            cc = write(ns, ack, strlen(ack));
            if(cc < 0){
                perror("写入数据失败");
                exit(EXIT_FAILURE);
            }

            memset(number,0, sizeof(number));
            cc = read(ns, number, sizeof(number) - 1);
            if(cc < 0){
                perror("读取数据失败");
                exit(EXIT_FAILURE);
            }

            cc = write(ns, ack, strlen(ack));
            if(cc < 0){
                perror("写入数据失败");
                exit(EXIT_FAILURE);
            }

            memset(type, 0, sizeof(type));
            cc = read(ns, type, sizeof(type) -1);
            if(cc < 0){
                perror("读取数据失败");
                exit(EXIT_FAILURE);
            }

            cc = pipe(pipe_n1n2);
            if(cc < 0){
                perror("创建管道失败");
                exit(EXIT_FAILURE);
            }

            pid_n1 = fork();
            if(pid_n1 < 0){
                perror("创建子进程失败");
                exit(EXIT_FAILURE);
            }else if (pid_n1 == 0){
                /*孙子进程1*/
                char db_file[BUFSIZE];

                close(ns);
                close(pipe_n1n2[0]);
                close(1);
                dup(pipe_n1n2[1]);
                close(pipe_n1n2[1]);

                snprintf(db_file,sizeof(db_file),"/var/local/games/%s/%s.txt",year,type);
                execlp("sort","sort","-n","-r",db_file,NULL);
                exit(EXIT_FAILURE);
            }

            cc = pipe(pipe_n2f);
            if(cc < 0){
                perror("创建管道失败");
                exit(EXIT_FAILURE);
            }

            pid_n2 = fork();
            if(pid_n2 < 0){
                perror("创建子进程失败");
                exit(EXIT_FAILURE);
            }else if (pid_n2 == 0){
                /*孙子进程2*/
                close(ns);

                close(pipe_n1n2[1]);
                close(0);
                dup(pipe_n1n2[0]);
                close(pipe_n1n2[0]);

                close(pipe_n2f[0]);
                close(1);
                dup(pipe_n2f[1]);
                close(pipe_n2f[1]);

                execlp("cut","cut","-f","1,4",NULL);
                exit(EXIT_FAILURE);
            }

            /*子进程*/
            close(pipe_n1n2[0]);
            close(pipe_n1n2[1]);

            close(pipe_n2f[1]);
            close(0);
            dup(pipe_n2f[0]);
            close(pipe_n2f[0]);

            close(1);
            dup(ns);
            close(ns);

            execlp("head","head","-n",number,NULL);
            exit(EXIT_FAILURE);
        }
        close(ns);
    }
    close(sd);
    return 0;
}
客户端代码
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define BUFSIZE 4096

int main(int argc, char *argv[]){
    int err;
    struct addrinfo hints, *res;
    char *remote_host;
    // 此处存在错误:类型应为char*而非char
    char remote_service;
    char year[BUFSIZE];
    char number[BUFSIZE];
    char type[BUFSIZE];

    if(argc < 3){
        fprintf(stderr,"参数错误:使用方式为 client server port\n");
        exit(EXIT_FAILURE);
    }

    memset(&hints,0,sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    remote_host = argv[1];
    remote_service = argv[2];

    if((err = getaddrinfo(remote_host,&remote_service,&hints,&res)) != 0){
        fprintf(stderr,"名称解析错误:%s\n",gai_strerror(err));
        exit(EXIT_FAILURE);
    }

    printf("请输入出版年份:\n");
    scanf("%s",year);

    do{
        int cc, sd, i = 0;
        struct addrinfo *ptr;
        uint8_t buffer[BUFSIZE];

        printf("请输入游戏数量:\n");
        scanf("%s",number);

        printf("请输入类型:\n");
        scanf("%s",type);

        for(ptr = res; ptr != NULL; ptr = ptr->ai_next){
            if((sd = socket(ptr->ai_family,ptr->ai_socktype,ptr->ai_protocol)) < 0){
                fprintf(stderr,"创建套接字失败\n");
                continue;
            }

            if(connect(sd,ptr->ai_addr,ptr->ai_addrlen) == 0){
                fprintf(stderr,"成功连接:%d\n",i);
                break;
            }

            close(sd);
            i++;
        }

        if(ptr == NULL){
            fprintf(stderr,"无法找到对应地址\n");
            exit(3);
        }

        if(write(sd,year,strlen(year)) < 0){
            perror("写入年份失败");
            exit(EXIT_FAILURE);
        }

        if(read(sd,buffer,sizeof(buffer)) < 0){
            perror("读取年份确认信息失败");
            exit(EXIT_FAILURE);
        }

        if(write(sd,number,strlen(number)) < 0){
            perror("写入数量失败");
            exit(EXIT_FAILURE);
        }

        if(read(sd,buffer,sizeof(buffer)) < 0){
            perror("读取数量确认信息失败");
            exit(EXIT_FAILURE);
        }

        if(write(sd,type,strlen(type)) < 0){
            perror("写入类型失败");
            exit(EXIT_FAILURE);
        }

        while((cc = read(sd,buffer,sizeof(buffer)) > 0)){
            write(1,buffer,cc);
        }

        if(cc < 0){
            perror("读取服务器结果失败");
            exit(EXIT_FAILURE);
        }

        close(sd);

        printf("请输入年份(输入end终止程序):\n");
        scanf("%s",year);
    }while(strcmp(year,"end") != 0);

    freeaddrinfo(res);

    return 0;
}   
问题原因及修复方案
  1. 客户端核心错误

    • remote_service被定义为char类型,但argv[2]是字符串指针,类型不匹配会导致getaddrinfo接收到乱码的服务名参数,直接引发名称解析失败。
    • 修复:将char remote_service;改为char *remote_service;,同时getaddrinfo调用改为getaddrinfo(remote_host,remote_service,&hints,&res);(去掉remote_service的取地址符)。
  2. 服务器核心错误

    • getaddrinfo的第一个参数传入了stderr(文件指针),而正确用法是配合AI_PASSIVE标志传入NULL,表示绑定到本地所有可用网络接口。
    • 修复:将err = getaddrinfo(stderr,service, &hints, &res);改为err = getaddrinfo(NULL,service, &hints, &res);。
  3. 主机名解析问题

    • 执行命令时使用的server主机名需要在本地/etc/hosts文件或DNS中有映射。如果是本地测试,可直接替换为localhost或127.0.0.1,避免主机名解析失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:55:24