2012-07-16 23 views
7

Tengo un módulo de adquisición de datos del cual me gustaría recopilar datos del puerto Ethernet. Estoy llegando en los pasos, actualmente me gustaría simplemente connect al servidor de un cliente. He usado la guía de Beej para obtener el código C básico. Pero cada vez me siento este error de conexión connect: Connection refused.C, zócalos: conexión Error rehusado

Esto es lo que hago:

  1. La red IP mencionado aquí es IP ESTÁTICA que he configurado.

  2. El número de puerto se establece en 50 000 en el lado del servidor y del lado del cliente conecto a esta IP en el puerto 50000.

  3. que generar y ejecutar la aplicación del lado del servidor y luego tratar de conectarse a él ejecutando una aplicación del lado del cliente.

Una duda acerca del lado del servidor, la aplicación del lado del servidor returns antes de que comience la aplicación del lado del cliente, por lo que debe mantenerlo funcionando (while(1);) para que pueda conectarse a él desde el lado del cliente?

¿Qué está pasando, estoy olvidando algo aquí? ¡Ayuda!

estoy pegando el código en C modificado muy ligeramente (números IP y el puerto son diferentes) de Beej para el lado del servidor lado y cliente aquí:

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 

} 

Respuesta

6

Tu servicio Falta el código r listen() y el código accept() para "esperar" una conexión al llamar a listen() y luego realizar un accept() para aceptar nuevas conexiones. ¿El ejemplo que estás usando no muestra cómo hacerlo? Por lo general, también bifurcará un nuevo hilo para cada nueva conexión.

Consulte http://www.linuxhowtos.org/C_C++/socket.htm para obtener más información.

Aquí hay un enlace a una aplicación más completa: http://www.thegeekstuff.com/2011/12/c-socket-programming/

+0

Gracias por los enlaces son una buena lectura. – HaggarTheHorrible

+0

@HeatfanJohn Comprobé un código que ha hecho esto, pero da como resultado el mismo problema. [Server.c] (https://paste.ubuntu.com/25599389/) [client.c] (https: //paste.ubuntu. com/25599391 /) – alhelal

+0

@BandaMuhammadAlHelal Su servidor parece estar escuchando en el puerto 9999 mientras su cliente intenta conectarse al puerto FTP_PORT (21). Cambia tu cliente para usar el puerto 9999 para conectarte. – HeatfanJohn

1

Por favor revisar el archivo de Server.c: no llama a escuchar() en absoluto!
Si el servidor objetivo no escucha en el puerto específico, devolverá el paquete RST al recibir el paquete SYN del cliente, por lo que connect() volverá con "Conexión rechazada".

flujo normal de las funciones del lado del servidor es socket -> bind -> escuchar -> Aceptar:

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

favor refiérase a http://beej.us/guide/bgnet/output/html/multipage/syscalls.html#listen

3

Sí, es necesario mantener el programa de servidor en funcionamiento.En su programa de servidor ha creado el socket usando socket() y enlazado a una dirección bind(), ahora necesita comenzar a escuchar las conexiones entrantes. Esto se hace con la llamada listen(). Una vez que el socket escucha las conexiones entrantes, debe usar la llamada accept() para aceptar realmente una conexión y obtener el socket para la comunicación con ese cliente en particular.

Como un ejemplo rápido, después de la freeaddrinfo se podría añadir el siguiente código:

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); 
} 

Este código tiene la deficiencia que se maneja un solo cliente a la vez. Hay algunas formas de manejar múltiples clientes simultáneos: procesos múltiples usando fork(), múltiples hilos o sondeo. Cada uno de estos enfoques están, en mi opinión, fuera del alcance de esta pregunta.

0

Recibí el error "conexión rechazada" debido a que no tenía la entrada del host remoto en el archivo/etc/hosts. La entrada debe estar presente en ambos lados. En las máquinas cliente/etc/hosts, debe haber una entrada de máquina servidor y viceversa en el siguiente patrón.

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

Esto resolvió el error que yo estaba en función getaddrinfo().

Cuestiones relacionadas