【问题标题】:C Client Server Connection RefusedC 客户端服务器连接被拒绝
【发布时间】:2017-01-26 00:31:10
【问题描述】:

我有一台运行 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;

}

【问题讨论】:

    标签: c sockets ubuntu client-server virtual-machine


    【解决方案1】:

    正如您在服务器控制台中看到的,对 gethostbyname 的调用失败。这个函数设置的是h_errno,而不是errno,所以不能用perror来输出错误。这就是为什么您会看到它声称“成功”。

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

    【讨论】:

    • 我猜你指的是这一行hostPtr=gethostbyname(hostname); if(NULL==hostPtr){ perror("gethostbyname()"); exit(1); },但正确的方法应该是什么?
    【解决方案2】:

    正如 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);
    

    在 server.c 中,当您设置 sin_addr 时,如上例所示。

    【讨论】:

      【解决方案3】:

      刚刚想通了。代码实际上没有问题。之所以出现错误,尤其是在以下行中,是因为我刚刚在虚拟框中安装了 ubuntu 后,我更改了 ubuntu 的设备名称,而没有更改 etc/hosts

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-27
        • 1970-01-01
        • 2014-01-10
        • 1970-01-01
        相关资源
        最近更新 更多