C 客户端服务器连接被拒绝

C Client Server Connection Refused

我有一台笔记本电脑 运行ning windows 10 并在 Oracle VM Virtualbox Machine 中安装了 ubuntu。我有以下服务器和客户端源代码。我 运行 先是服务器,然后是客户端。但它给了我一个拒绝连接。试过netstat -ntlp 发现居然没有端口监听我输入的具体端口

server.c

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

int _GetHostName(char *buffer, int lenght);

const char MESSAGE[]="Hello, World!\n";
const int BACK_LOG=5;

int main(int argc, char *argv[]){
    int serverSocket=0, on=0, port=0, status=0, childPid=0;
    struct hostent *hostPtr=NULL;
    char hostname[80]="";
    struct sockaddr_in serverName={0};

    if(2!= argc){
        fprintf(stderr, "Usage : %s <port>\n", argv[0]);
        exit(1);
    }
    port=atoi(argv[1]);
    serverSocket=socket(PF_INET,SOCK_STREAM, IPPROTO_TCP);
    if(-1==serverSocket){
        perror("socket()");
        exit(1);
    }

    on=1;
    status=setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    if(-1==status){
        perror("setsockopt(...,SO_REUSEADDRE,...)");
    }

    {
        struct linger linger={0};
        linger.l_onoff=1;
        linger.l_linger=30;
        status=setsockopt(serverSocket, SOL_SOCKET, SO_LINGER, (const char*)&linger, sizeof(linger));
        if(-1==status){
            perror("setsockopt(...,SO_LINGER,...)");
        }
    }

    status=_GetHostName(hostname, sizeof(hostname));
    if(-1==status){
        perror("_GetHostName()");
        exit(1);
    }

    hostPtr=gethostbyname(hostname);
    if(NULL==hostPtr){
        perror("gethostbyname()");
        exit(1);
    }

    (void)memset(&serverName,0,sizeof(serverName));
    (void)memcpy(&serverName.sin_addr, hostPtr->h_addr,hostPtr->h_length);

    serverName.sin_family=AF_INET;
    serverName.sin_port=htons(port);

    status=bind(serverSocket, (struct sockaddr*)&serverName,sizeof(serverName));
    if(-1==status){
        perror("bind");
        exit(1);
    }


    status=listen(serverSocket, BACK_LOG);
    if(-1==status){
        perror("listen()");
        exit(1);
    }

    for(;;){
        struct sockaddr_in clientName={0};
        int slaveSocket, clientLength=sizeof(clientName);

        (void)memset(&clientName,0,sizeof(clientName));

        slaveSocket=accept(serverSocket,(struct sockaddr*)&clientName, & clientLength);
        if(-1==slaveSocket){
            perror("accept()");
            exit(1);
        }

        childPid=fork();

        switch(childPid){
            case -1:perror("fork()");
            exit(1);
            case 0: close(serverSocket);
            if(-1==getpeername(slaveSocket, (struct sockaddr*)&clientName, &clientLength)){
                perror("getpeername()");
            }else{
                printf("Connection request from %s \n", inet_ntoa(clientName.sin_addr));
            }

            /*
                Server Application specific code here
                response to client
            */
            write(slaveSocket,MESSAGE,strlen(MESSAGE));
            close(slaveSocket);
            exit(0);
            default:close(slaveSocket);
        }
    }
    return 0;
}

int _GetHostName(char *buffer,int length){
    struct utsname sysname={0};
    int status=0;

    status=uname(&sysname);
    if(-1!=status){
        strncpy(buffer,sysname.nodename,length);
    }
    return(status);
}

client.c

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

int main(int argc, char *argv[]){
    int clientSocket, remotePort, status=0;
    struct hostent *hostPtr=NULL;
    struct sockaddr_in serverName={0};
    char buffer[256]="";
    char *remoteHost=NULL;

    if(3!=argc){
        fprintf(stderr, "Usage: %s <serverHost> <serverPort> \n",argv[0]);
        exit(1);
    }
    remoteHost=argv[1];
    remotePort=atoi(argv[2]);
    clientSocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(-1==clientSocket){
        perror("socket()");
        exit(1);
    }

    hostPtr=gethostbyname(remoteHost);
    if(NULL==hostPtr){
        hostPtr=gethostbyaddr(remoteHost,strlen(remoteHost), AF_INET);
        if(NULL==hostPtr){
            perror("Error resolving server address ");
            exit(1);
        }
    }
    serverName.sin_family=AF_INET;
    serverName.sin_port=htons(remotePort);
    (void)memcpy(&serverName.sin_addr,hostPtr->h_addr,hostPtr->h_length);
    status=connect(clientSocket,(struct sockaddr*)&serverName,sizeof(serverName));
    if(-1==status){
        perror("connect()");
        exit(1);
    }
    //CLIENT SPECIFIC HERE

    while(0 < (status=read(clientSocket, buffer,sizeof(buffer)-1)))
        printf("%d: %s", status, buffer);
        if(-1==status)perror("read()");
        close(clientSocket);
        return 0;

}

如您在服务器控制台中所见,对 gethostbyname 的调用失败。这个函数设置的是h_errno,不是errno,所以不能用perror来输出错误。这就是为什么你看到它声称 "success".

不过我看不出在这里使用 gethostbyname 有什么意义,大多数服务器在用户未指定地址时默认使用 INADDR_ANY。

正如 Joni 已经指出的那样,您的程序在 server.c 中的 gethostbyname() 处失败,然后退出。因此没有端口被绑定,因为你的程序不再是 运行。

如果不是真的需要,请不要使用 gethostbyname() 函数,直接设置 sin_addr,就像以下示例之一:

// let the kernel fill in the address of your interface for you automatically
serverName.sin_addr.s_addr = htonl(INADDR_ANY);

// use a loopback address (127.0.0.1) = localhost
serverName.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

// use whatever address you like
serverName.sin_addr.s_addr = inet_addr("127.1.1.1");

不要忘记删除行

memcpy(&serverName.sin_addr, hostPtr->h_addr,hostPtr->h_length);

in server.c 当你像上面的例子一样设置 sin_addr 时。

刚刚弄明白了。其实代码没有问题。之所以在下面这行特别出错,是因为我刚刚在虚拟盒子中安装了ubuntu之后,我更改了ubuntu的设备名称,而没有更改etc/hosts

hostPtr=gethostbyname(hostname);
if(NULL==hostPtr){
    perror("gethostbyname()");
    exit(1);
}