2016-06-15 6 views
0

Obwohl es richtig umgesetzt zu sein scheint, es bei der Rückkehr mir hält ERROR, wenn ich eine Verbindung herstellen mit der Loopback-Adresse (127.0.0.1).TCP Client-Server "schlechte Adresse" Fehler (in C)

Neben einem einfachen TCP Client/Server-Verbindung, ich habe einen weiteren Fall hinzugefügt:

Wenn der Client versucht, Daten zu senden, aber findet die Verbindung geschlossen, auch ist es geschlossen. Ich führe es durch Prüfung, ob empfangene Daten gleich 0 (recv) ist.

Gegeben Fehler:

CLIENT: 
Welcome to the Client mode 
Please, enter the Server's IP Address and Port (eg. 192.128.192.0 1320) 
127.0.0.1 2700 
Connected to the server. Now you can send messages 
Please, enter a message. Enter "FINISH" if you want to finish the connection 
ECHO 
client: connection closed ->: Success 
(1 bytes)Closing the connection 

SERVER: 
Hello and welcome to the Server mode 
Please, enter the Server's Port (eg. 1320) 
2700 
Server socket successfully configured 
Server listening [Clients allowed: 5] 
server: accept error: Bad address 

Kunde Umsetzung:

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 

#include <netinet/in.h> 
#include <netinet/ip.h> 

/** 

struct sockaddr{ 
    uint8_t sa_len; // struct length 
    sa_family_t sa_family; //protocol family: AF_XXX 
    char sa_data[8]; //socket addr 
} 

*/ 

//void notConnected(); 
int main(){ 

    struct sockaddr_in serv_addr; //port + ip_addr 
    int     my_socket, tcp_port; 
    char    serv_host_addr[30]; 

    char    buffer[1024], inbuff[1024]; 
    int     io_buffer; 

    printf("Welcome to the Client mode\n"); 

    //CONFIGURING THE CONNECTION 
    my_socket = socket(AF_INET, SOCK_STREAM, 0);//(2) 
    if(my_socket < 0){ 
     perror("client: socket() error ->"); 
     exit(EXIT_FAILURE); 
    } 

    bzero(&serv_addr, sizeof(serv_addr));//(4) 
    printf("Please, enter the Server's IP Address and Port (eg. 192.128.192.0 1320) \n"); 
    scanf("%s %d", serv_host_addr, &tcp_port);//(1) 


    serv_addr.sin_family = AF_INET ; 
    serv_addr.sin_port = htons(tcp_port); 
    if(inet_pton(AF_INET,serv_host_addr,&serv_addr.sin_addr) < 1){ 
     perror("client: inet_pton() error ->"); 
     exit(EXIT_FAILURE); 
    } 

    if((connect(my_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0)//(5) 
    { 
     perror("client: connect() error ->"); 
     exit(EXIT_FAILURE); 
    } 


    //ONCE CONNECTED, START THE SENDING/RECEIVING 
    printf("Connected to the server. Now you can send messages\n"); 
    bzero(&buffer, sizeof(buffer)); 

    while(strcmp(buffer, "OK\n") != 0){ 

     printf("Please, enter a message. Enter \"FINISH\" if you want to finish the connection\n");//(3) 
     bzero(&buffer, sizeof(buffer)); 
     fgets(buffer, sizeof(buffer), stdin); 

     io_buffer = send(my_socket, buffer, strlen(buffer),0);//(6) 
     if(io_buffer < 0){ 
      perror("client: send() error ->"); 
      exit(EXIT_FAILURE); 
     } 
     printf("ECHO %s (%d bytes)", buffer, io_buffer); 


     //RECEIVE AND CHECK IF CONNECTION HAS BEEN CLOSED 
     io_buffer = recv(my_socket, buffer, sizeof(buffer),0); 
     if(io_buffer < 0){ 
      perror("client: recv() error ->"); 
      exit(EXIT_FAILURE); 
     } 
     else if(io_buffer == 0){ //THIS IS SERVER IS CLOSED 
      perror("client: connection closed ->"); 
      break; 
     } 
     printf("ECHO %s (%d bytes)", buffer, io_buffer); 

    } 

    printf("Closing the connection \n"); 
    for(int i=0; i < 5; i++){ 
     printf(". "); 
     usleep(500000); 
    } 
    close(my_socket); 
} 

Server Implementierung:

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 

#define LISTENQ 5 

int main() 
{ 
    struct sockaddr_in cli_addr, serv_addr; 
    char    buffer[1024]; 
    int     serv_socket, cli_socket, clilen, io_buffer; 
    int     tcp_port; 

printf("Hello and welcome to the Server mode\n"); 

// ASKING FOR PORT NUMBER 
    if((serv_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0){ 
     perror("server: can't open stream socket"); 
     exit(EXIT_FAILURE); 
    } 

printf("Please, enter the Server's Port (eg. 1320) \n"); 
    scanf("%d", &tcp_port); 

// CONFIGURING THE CONNECTION 
    serv_addr.sin_family  = AF_INET; 
    serv_addr.sin_port   = htons(tcp_port); 
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 

// ASSIGNING A NAME TO THE SOCKET 
    if(bind(serv_socket,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){ 
     perror("server: can't assign a name to the socket"); 
     exit(EXIT_FAILURE); 
    } 
printf("Server socket successfully configured\n"); 

printf("Server listening [Clients allowed: %d]\n", LISTENQ); 
    if(listen(serv_socket, LISTENQ) < 0) 
    { 
     perror("server: fail to listen network"); 
     exit(EXIT_FAILURE); 
    } 

// READ & WRITE STREAM 
    while(1){ 
     //returns a file descriptor for the client 
     cli_socket = accept(serv_socket,(struct sockaddr *) &cli_addr,(socklen_t *) sizeof(cli_addr)); 

     if(cli_socket < 0){ 
      perror("server: accept error"); 
      exit(EXIT_FAILURE); 
     } 
     printf("Server successfully connected to Client\n"); 

     while(1) 
     { 

      if ((io_buffer=recv(cli_socket,buffer,sizeof(buffer),0))<0){ 
       perror("ERROR: recv"); 
       exit(EXIT_FAILURE); 
      } 
      printf("\"%s\" received from client", buffer); 

      if(strcmp(buffer, "FINISH") == 0) 
      { 
       break; 
      } 

      if ((io_buffer=send(cli_socket,buffer,strlen(buffer),0))!=strlen(buffer)){ 
       perror("ERROR: send"); 
       exit(EXIT_FAILURE); 
      } 

      bzero(buffer, sizeof(buffer)); 
     } 

     strcpy(buffer, "OK"); 
     if ((io_buffer=send(cli_socket, buffer, strlen(buffer), 0)) != strlen(buffer)){ 
      perror("ERROR: send"); 
      exit(EXIT_FAILURE); 
     } 
     printf("\"OK\" message sent to the Client.\n"); 
     printf("Closing the connection \n"); 
     for(int i=0; i < 5; i++) 
     { 
      printf(". "); 
      usleep(500000); 
     } 
     close(cli_socket); 
    } 
} 
+0

Ist Ihr "Bad Address" -Problem immer noch vorhanden, nachdem Sie die Änderung vorgenommen haben, schlug ich auf CR vor? – forsvarir

+0

Dieser Code weist das beschriebene Problem nicht auf, aber der ursprüngliche Code tat dies. – EJP

+0

zur besseren Lesbarkeit und Verständnis: 1) konsistent den Code einrücken. Nach jeder öffnenden Klammer '{' einrücken. Einrücken vor jeder schließenden Klammer '}' .. 2) folgen Sie dem Axiom: * nur eine Anweisung pro Zeile und (höchstens) eine Variablendeklaration pro Anweisung. * – user3629249

Antwort

9

In Ihrer ursprünglichen Frage, Ihr Anruf annehmen wie folgt aussieht:

cli_socket = accept(serv_socket,(struct sockaddr *) &cli_addr, 
        (socklen_t *) sizeof(cli_addr)); 

Dies passiert "(socklen_t *) sizeof (cli_addr)" als dritten Parameter zu akzeptieren. Dies soll ein Hinweis auf die Größe der Struktur sein. Sie sollten einen Zeiger auf socklen_t übergeben, der die Größe der als Parameter zwei übergebenen Struktur enthält. Die Größe, die Sie gerade übergeben, wird als eine Adresse interpretiert, die dann Ihr Programm zum Absturz bringt, wenn es referenziert wird. Der Code sollte wie folgt aussehen:

socklen_t cli_addr_size = sizeof(cli_addr); 
cli_socket = accept(serv_socket,(struct sockaddr *) &cli_addr, 
        &cli_addr_size); 
+1

' cli_addr_size' sollte als 'socklen_t' deklariert werden (nicht' socket_t'), aber ansonsten gute Antwort –

+0

@GilHamilton Danke, I habe es aktualisiert. – forsvarir