简体   繁体   English

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

[英]C Client Server Connection Refused

I have a laptop running windows 10 and intalled ubuntu in Oracle VM Virtualbox Machine. 我有一台笔记本电脑在Oracle VM Virtualbox Machine中运行Windows 10和安装的ubuntu。 I have the following server and and client source code. 我有以下服务器和客户端源代码。 I run the server first then the client. 我先运行服务器,然后运行客户端。 But it gave me a connection refused. 但这给了我一个拒绝的联系。 Tried netstat -ntlp then found out that there is actually no port listening to the specific port I typed. 经过尝试的netstat -ntlp然后发现实际上没有端口在监听我键入的特定端口。

在此处输入图片说明

server.c 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 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;

}

As you can see in the server console, the call to gethostbyname is failing. 在服务器控制台中可以看到,对gethostbyname的调用失败。 This function sets h_errno, not errno, so you can't use perror to output the error. 此函数设置h_errno而不是errno,因此您不能使用perror输出错误。 This is why you see it claim "success". 这就是为什么您看到它声称“成功”的原因。

I don't see the point of using gethostbyname here though, most servers default to using INADDR_ANY when the address isn't specified by the user. 我在这里看不到使用gethostbyname的意义,当用户未指定地址时,大多数服务器默认使用INADDR_ANY。

As Joni already pointed out, your program fails at gethostbyname() in server.c and then exits. 正如Joni所指出的那样,您的程序在server.c中的gethostbyname()处失败,然后退出。 Therefore no port gets bound since your program isn't running anymore. 因此,由于您的程序不再运行,因此没有端口绑定。

Just don't use the gethostbyname() function if it's not really necessary and set sin_addr directly like in one of the following examples: 只是如果确实没有必要,不要使用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");

Don't forget to remove the line 别忘了删除行

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

in server.c when you set sin_addr like in the examples above. 如上例所示,在server.c中设置sin_addr时。

Just figured it out. 只是想通了。 There is actually no problem in the code. 代码中实际上没有问题。 The reason why I got an error particularly in the following line is that because just after I installed ubuntu in the virtual box, I changed the device name of the ubuntu without changing the etc/hosts . 之所以出现错误,尤其是在下一行中出现错误,是因为在虚拟机中安装了ubuntu之后,我更改了ubuntu的设备名称而未更改etc/hosts

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM