9

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

这就是我所做的:

  1. 这里提到的网络IP是我配置的STATIC IP 。

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

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

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

怎么了,我在这里忘记了什么?帮助!

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

服务器.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

}

客户端.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

4 回答 4

7

您的服务器代码丢失listen()accept()代码通过调用 listen() 来“等待”连接,然后执行一个accept()以接受新连接。您使用的示例没有显示如何做到这一点吗?通常,您还将为每个新连接创建一个新线程。

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

这是一个更完整实现的链接:http ://www.thegeekstuff.com/2011/12/c-socket-programming/

于 2012-07-16T03:24:25.453 回答
5

是的,您需要保持服务器程序运行。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()、多线程或轮询。在我看来,这些方法中的每一种都超出了这个问题的范围。

于 2012-07-16T03:32:42.550 回答
1

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

服务器端的正常功能流程是 socket -> bind -> listen -> accept :

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

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

于 2012-07-16T03:25:49.227 回答
0

I was getting the error "connection refused" due to not having the entry of remote host in /etc/hosts file. Entry should be present both side. In Client machines /etc/hosts, there should be a entry of server machine and vice versa in below pattern.

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

This solved the error which i was in getaddrinfo() function.

于 2013-05-22T09:26:51.890 回答