C,套接字:连接被拒绝错误

时间:2012-07-16 03:14:54

标签: c sockets

我有一个数据采集模块,我想从以太网端口收集数据。 我正在逐步实现,目前我只想connect来自客户端的服务器。我用过Beej的指南来获取基本的C代码。但我只是不断收到此连接错误connect: Connection refused.

这就是我的工作:

  1. 此处提到的网络IP是我已配置的 STATIC IP

  2. 端口号在服务器端设置为50000,从客户端端口连接到端口50000上的此IP。

  3. 我构建并运行服务器端应用程序,然后尝试通过运行客户端应用程序连接到它。

  4. 在启动客户端应用程序之前,服务器端,服务器端应用程序returns有一个疑问,所以我应该让它继续运行(while(1);)以便我可以从客户端连接到它吗?

    我在这里遗忘了什么?救命啊!

    我正在粘贴稍微修改过的(IP和端口号不同)Beej的服务器端和客户端的C代码:

    Server.c

    /*
    ** server.c
    */
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    
    
    
    int main(int argc, char *argv[])
    {
        // code for a server waiting for connections
        // namely a stream socket on port 3490, on this host's IP
        // either IPv4 or IPv6.
        int sockfd;
        struct addrinfo hints, *servinfo, *p;
        int rv;
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP address
    
        if ((rv = getaddrinfo(NULL, "50000", &hints, &servinfo)) != 0)
        {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
            exit(1);
        }
    
        // loop through all the results and bind to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next) 
        {
            if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1) 
            {
                perror("socket");
                continue;
            }
            if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
            {
                close(sockfd);
                perror("bind");
                continue;
            }
            break; // if we get here, we must have connected successfully
        }
    
        if (p == NULL) 
        {
            // looped off the end of the list with no successful bind
            fprintf(stderr, "failed to bind socket\n");
            exit(2);
        }
    
        freeaddrinfo(servinfo); // all done with this structure
    
    }
    

    Client.c

    /*
    ** client.c
    */
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    
    int main(int argc, char *argv[])
    {
        // code for a client connecting to a server
        // namely a stream socket to www.example.com on port 80 (http)
        // either IPv4 or IPv6
        int sockfd;
        struct addrinfo hints, *servinfo, *p;
        int rv;
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
        hints.ai_socktype = SOCK_STREAM;
        if ((rv = getaddrinfo("192.168.2.4", "50000", &hints, &servinfo)) != 0) 
        {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
            exit(1);
        }
        // loop through all the results and connect to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
            if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1) 
            {
                perror("socket");
    
            continue;
            }
            if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) 
            {
                close(sockfd);
                perror("connect");
                continue;
            }
            break; // if we get here, we must have connected successfully
        }
    
        if (p == NULL)
        {
            // looped off the end of the list with no connection
            fprintf(stderr, "failed to connect\n");
            exit(2);
        }
    
        freeaddrinfo(servinfo); // all done with this structure
    
    }
    

4 个答案:

答案 0 :(得分:7)

您的服务器代码缺少listen()accept()代码,通过调用listen()然后执行accept()接受新连接来“等待”连接。您使用的示例不显示如何执行此操作吗?通常,您还将为每个新连接分叉一个新线程。

有关详细信息,请参阅http://www.linuxhowtos.org/C_C++/socket.htm

以下是更完整实施的链接:http://www.thegeekstuff.com/2011/12/c-socket-programming/

答案 1 :(得分:3)

是的,您需要保持服务器程序正常运行。在您的服务器程序中,您使用socket()创建了套接字并绑定到地址bind(),现在您需要开始侦听传入连接。这是通过listen()调用完成的。一旦套接字正在侦听传入连接,您必须使用accept()调用来实际接受连接并获取套接字以与该特定客户端进行通信。

作为一个简单的例子,在freeaddrinfo之后你可以添加以下代码:

listen(sockfd, 8); /* allow up to 8 pending connections, i.e. created but not accepted */
while (1) {
  int clientfd;
  struct sockaddr_in client_addr;
  socklen_t client_addr_len = sizeof(struct sockaddr_in);
  clientfd = accept(sockfd, &client_addr, &client_addr_len);
  /* communicate with client by send()/recv() or write()/read() on clientfd */
  close(clientfd);
}

此代码的缺点是一次只能处理一个客户端。有几种方法可以处理多个并发客户端:使用fork(),多个线程或轮询的多个进程。在我看来,这些方法中的每一种都超出了本问题的范围。

答案 2 :(得分:1)

请查看您的Server.c文件:它根本不会调用listen()!
如果目标服务器没有侦听指定的端口,那么它会在从客户端收到SYN数据包时返回RST数据包,因此connect()将返回“Connection refused”。

服务器端的正常功能流是套接字 - &gt; bind - &gt;听 - &gt;接受:

getaddrinfo();
socket();
bind();
listen();
/* accept() goes here */ 

请参阅https://beej.us/guide/bgnet/html/multi/syscalls.html#listen

答案 3 :(得分:0)

由于没有在/ etc / hosts文件中输入远程主机,我收到错误“连接被拒绝”。入境应该存在于两边。在客户端机器/ etc / hosts中,应该有一个服务器机器的条目,反之亦然,在下面的模式中。

<ip address> <hostname with domain> <alias hostname>

这解决了我在getaddrinfo()函数中的错误。