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

时间:2016-09-18 04:39:37

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

我有一台运行Windows 10的笔记本电脑,并在Oracle VM Virtualbox Machine中安装了ubuntu。我有以下服务器和客户端源代码。我首先运行服务器然后运行客户端。但它给了我拒绝连接。尝试netstat -ntlp后发现实际上没有端口监听我输入的特定端口。

enter image description here

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;

}

3 个答案:

答案 0 :(得分:2)

正如您在服务器控制台中看到的,对gethostbyname的调用失败。此函数设置h_errno,而不是errno,因此您无法使用perror输出错误。这就是为什么你看到它宣称成功&#34;。

我在这里没有看到使用gethostbyname的观点,但是当用户未指定地址时,大多数服务器默认使用INADDR_ANY。

答案 1 :(得分:1)

正如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);
当您在上面的示例中设置sin_addr时,在server.c中

答案 2 :(得分:0)

刚想通了。代码中实际上没有问题。我在下一行中遇到错误的原因是,因为刚在虚拟框中安装了ubuntu后,我更改了ubuntu的设备名称,而没有更改etc/hosts

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