2012-07-16 28 views
7

Ho un modulo di acquisizione dati dal quale vorrei raccogliere i dati dalla porta Ethernet. Ci sto arrivando nei passaggi, attualmente mi piacerebbe solo il connect al server da un client. Ho usato la guida di Beej per ottenere il codice C di base. Ma ho appena continuo a ricevere questo errore di connessione connect: Connection refused.C, Socket: errore di connessione rifiutata

Questo è quello che faccio:

  1. La rete IP qui menzionato è IP STATICO che ho configurato.

  2. Il numero di porta è impostato su 50000 sul lato server e dal lato client si collega a questo IP sulla porta 50000.

  3. ho compilare ed eseguire l'applicazione lato server e quindi provare a connettersi ad esso eseguendo un'applicazione lato client.

Un dubbio su lato server, applicazioni lato server returns prima di iniziare l'applicazione lato client, quindi devo mantenere in esecuzione (while(1);) in modo che io possa connettersi ad esso dal lato client?

Cosa non va sto dimenticando qualcosa qui? Aiuto!

Sto incollando il (numeri IP e la porta sono diversi) di codice C molto leggermente modificata del Beej per il lato client e lato server qui:

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 

} 

risposta

6

Il vostro servizio il codice r manca listen() e il codice accept() per "attendere" una connessione chiamando listen() e quindi eseguendo un accept() per accettare nuove connessioni. L'esempio che stai usando non mostra come farlo? In genere si assegnerà anche una nuova discussione per ogni nuova connessione.

Vedere http://www.linuxhowtos.org/C_C++/socket.htm per ulteriori informazioni.

Ecco un link ad un'implementazione più completa: http://www.thegeekstuff.com/2011/12/c-socket-programming/

+0

Grazie per i link sono una buona lettura. – HaggarTheHorrible

+0

@HeatfanJohn Ho controllato un codice che ha fatto questi, ma risulta lo stesso problema. [Server.c] (https://paste.ubuntu.com/25599389/) [client.c] (https: //paste.ubuntu. it/25599391 /) – alhelal

+0

@BandaMuhammadAlHelal Il server sembra in ascolto sulla porta 9999 mentre il client sta tentando di connettersi alla porta FTP_PORT (21). Cambia il tuo client per utilizzare la porta 9999 per connettersi. – HeatfanJohn

1

Si prega di guardare il file server.c: non chiama ascolta() a tutti!
Se il server di destinazione non ascolta sulla porta specifica, restituisce il pacchetto RST dopo aver ricevuto il pacchetto SYN dal client, quindi connect() restituisce con "Connessione rifiutata".

normale flusso delle funzioni lato server è presa -> bind -> ascoltare -> Accetta:

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

prega di fare riferimento al http://beej.us/guide/bgnet/output/html/multipage/syscalls.html#listen

3

Sì, è necessario mantenere il programma server in esecuzione.Nel tuo programma server hai creato il socket utilizzando socket() e associato a un indirizzo bind(), ora devi iniziare ad ascoltare le connessioni in entrata. Questo viene fatto con la chiamata listen(). Una volta che il socket è in ascolto per le connessioni in entrata, è necessario utilizzare la chiamata accept() per accettare effettivamente una connessione e ottenere il socket per la comunicazione con quel particolare client.

Come esempio veloce, dopo la freeaddrinfo si potrebbe aggiungere il seguente codice:

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

Questo codice ha la carenza che solo un cliente alla volta viene gestito. Esistono diversi modi per gestire più client simultanei: più processi che utilizzano fork(), più thread o polling. Ognuno di questi approcci è, a mio parere, al di fuori della portata di questa domanda.

0

Stavo ricevendo l'errore "connessione rifiutata" a causa di non avere la voce dell'host remoto nel file/etc/hosts. L'entrata dovrebbe essere presente su entrambi i lati. Nei computer client/etc/hosts, dovrebbe esserci una voce della macchina del server e viceversa sotto il modello.

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

Questa risolto l'errore che gli era in funzione getaddrinfo().

Problemi correlati