2012-07-16 21 views
7

Ich habe ein Datenerfassungsmodul, von dem ich Daten vom Ethernet-Port sammeln möchte. Ich komme in Schritten, derzeit möchte ich nur connect Server von einem Client. Ich habe Beejs Anleitung benutzt, um den grundlegenden C-Code zu bekommen. Aber ich halte ihn nur connect Fehler bekommen connect: Connection refused.C, Sockel: Verbindung Fehler verweigert

Das ist, was ich tue:

  1. Die Netzwerk-IP hier erwähnt ist STATIC IP die ich konfiguriert haben.

  2. Die Portnummer 50000 auf Server-Seite und von der Clientseite gesetzt ich an diese IP auf dem Port 50000.

  3. ich baue und führen Sie die Server-Seite Anwendung verbinden und dann versuchen, eine Verbindung herzustellen indem Sie eine clientseitige Anwendung ausführen.

Ein Zweifel über Server-Seite, Server-seitige Anwendung returns, bevor ich die Client-Seite Anwendung zu starten, so soll ich halte es läuft (while(1);), so dass ich es von der Client-Seite einer Verbindung herstellen kann?

Was ist los, vergesse ich hier etwas? Hilfe!

ich das sehr leicht modifiziert bin Einfügen (IP und Port-Nummern sind unterschiedlich) Beej des C-Code für Server-Seite und Client-Seite hier:

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 

} 

Antwort

6

Ihr dienen R-Code fehlt listen() und accept() Code auf "warten" für eine Verbindung durch den Aufruf von listen() und dann eine accept() ausführen, um neue Verbindungen zu akzeptieren. Zeigt das von Ihnen verwendete Beispiel nicht, wie das geht? In der Regel wird auch für jede neue Verbindung ein neuer Thread erstellt.

Weitere Informationen finden Sie unter http://www.linuxhowtos.org/C_C++/socket.htm.

Hier ist ein Link zu einer vollständigeren Umsetzung: http://www.thegeekstuff.com/2011/12/c-socket-programming/

+0

Vielen Dank für die Links, die sie gelesen haben. – HaggarTheHorrible

+0

@HeatfanJohn Ich habe einen Code überprüft, der das gemacht hat, aber das gleiche Problem hat. [Server.c] (https://paste.ubuntu.com/25599389/) [client.c] (https: //paste.ubuntu. com/25599391 /) – alhelal

+0

@BandaMuhammadAlHelal Ihr Server scheint Port 9999 zu überwachen, während Ihr Client versucht, eine Verbindung zum Port FTP_PORT (21) herzustellen. Ändern Sie Ihren Client, um Port 9999 zu verwenden, um eine Verbindung herzustellen. – HeatfanJohn

1

Betrachten Sie bitte Ihre server.c Datei: es ruft nicht hören() überhaupt nicht!
Wenn der Zielserver den spezifizierten Port nicht abhört, gibt er beim Empfang eines SYN-Pakets vom Client ein RST-Paket zurück, so dass connect() mit "Connection refused" zurückgegeben wird.

normaler Fluss der Funktionen auf Server-Seite ist socket -> bind -> hören -> akzeptieren:

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

Bitte beachten Sie http://beej.us/guide/bgnet/output/html/multipage/syscalls.html#listen

3

Ja, Sie müssen das Serverprogramm am Laufen zu halten.In Ihrem Serverprogramm haben Sie den Socket mit socket() erstellt und an eine Adresse bind() gebunden, jetzt müssen Sie auf eingehende Verbindungen warten. Dies geschieht mit dem listen() Aufruf. Sobald der Socket auf eingehende Verbindungen wartet, müssen Sie den accept() Aufruf verwenden, um tatsächlich eine Verbindung zu akzeptieren und den Socket für die Kommunikation mit diesem bestimmten Client abrufen.

Als kurzes Beispiel, nach dem freeaddrinfo Sie den folgenden Code hinzufügen könnten:

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

Dieser Code hat den Mangel, dass nur ein Client zu einem Zeitpunkt behandelt wird. Es gibt mehrere Möglichkeiten, mehrere gleichzeitige Clients zu verarbeiten: mehrere Prozesse mit fork(), mehreren Threads oder Polling. Jeder dieser Ansätze ist meines Erachtens nicht Gegenstand dieser Frage.

0

Ich bekam den Fehler "Verbindung abgelehnt", da der Eintrag des entfernten Hosts in der Datei/etc/hosts nicht vorhanden war. Der Eintrag sollte auf beiden Seiten vorhanden sein. In Client-Rechnern/etc/hosts sollte ein Eintrag des Server-Rechners und umgekehrt in dem folgenden Muster enthalten sein.

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

Dies löste den Fehler, die ich in getaddrinfo() Funktion war.