2010-03-01 14 views
10

EDIT: der Code unten fixiert wurde ordnungsgemäß zu empfangen und senden und für das tatsächliche Bytes der gesendeten Nachrichten annd empfangen (letztere dank EJP) zu berücksichtigenSocket-Programmierung: recv/Lese Ausgabe

Ich bin Programmierung mit C in Unix.

Ich habe Server und Client, die msgs austauschen sollen. Während der Client scheinbar Nachrichten zu senden scheint, empfängt der Server die Nachrichten nicht, die der Client sendet. Ich habe versucht mit recv() und read() (ich weiß, dass sie praktisch die gleiche Sache sind, aber mit zusätzlichen Flags auf recv()), aber ich habe kein Glück und ich bin mir nicht wirklich sicher, was das Problem wirklich ist.

Ich gebe sleep(3) in den Client-Code nach jedem Senden einer Nachricht, aber ich sehe, dass sobald Client und Server verbunden sind, schließt der Server sofort, ohne auf die eingehenden Nachrichten zu warten. Was mache ich falsch?

Dies ist der clientseitigen Code:

#define SERVER_TCP_PORT 11112 
#define MAX_DATA_SIZE 500 

int main(int argc, char * argv[]) 
{ 
    int sockfd; 
    char * host; 
    char msg[MAX_DATA_SIZE];/* = "get my msg!\n";*/ 
    int msg_len; 

    struct hostent * hp; 
    struct sockaddr_in client_address, server_address; 


    printf("y halo thar\n"); 


    // looking up from the host database 
    if (argc == 2) 
     host = argv[1]; 
    else 
     exit(1); 
    printf("sdf\n"); 


    hp = gethostbyname(host); 
    if (!hp) 
     exit(1); 
    printf("host found\n"); 


    // setting up address and port structure information 
    bzero((char *) &server_address, sizeof(server_address)); // copy zeroes into string 
    server_address.sin_family = AF_INET; 
    bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length); 
    server_address.sin_port = htons(SERVER_TCP_PORT); 
    printf("set\n"); 


    // opening up socket 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     exit(1); 
    printf("opened\n"); 


    // connecting 
    if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) 
     exit(1); 
    printf("connected\n"); 


    int i; 

    for (i = 0; i < MAX_DATA_SIZE; ++i) 
    { 
     msg[i] = '.'; 
    } 

    msg[MAX_DATA_SIZE-1] = '\0'; 

    for(i = 0; i < 11; i++) 
    { 
     // send message to connected socket 
     msg_len = write(sockfd, msg, MAX_DATA_SIZE); 
     if(msg_len < 1) 
      printf("notsent\n"); 
     else 
      printf("%i bytes sent\n", msg_len); 

     // recieve messages from connected socket 
     msg_len = read(sockfd, msg, MAX_DATA_SIZE); 
     if (msg_len < 1) 
      printf("not recieved\n"); 
     else 
     { 
      printf("%i bytes received\n", msg_len); 
      printf(msg); 
      printf("\n"); 

     } 
    } 


    // close connection 
    close(sockfd); 
    printf("closed\n"); 

} 

und dies ist der Server-Seite

#define SERVER_TCP_PORT 11112 
#define MAX_DATA_SIZE 500 


int main() 
{ 

    printf("o halo thar\n"); 

    int sockfd, new_sockfd; 
    int client_addr_len; 
    char msg [MAX_DATA_SIZE]; 
    int msg_len; 
    char got_msg [11] = "got ur msg\0"; 
    struct sockaddr_in server_address, client_address; 


    // setting up address and port structure information 
    bzero((char *) &server_address, sizeof(server_address)); // copy zeroes into string 
    server_address.sin_family = AF_INET; 
    server_address.sin_addr.s_addr = htonl(INADDR_ANY); 
    server_address.sin_port = htons(SERVER_TCP_PORT); 


    // opening up socket 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     exit(1); 
    printf("socket is opened\n"); 


    // binding 
    if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) 
     exit(1); 
    printf("socket is bound\n"); 


    // listening 
    listen(sockfd,5); 
    printf("listening\n"); 

    // block and wait for an incoming connection 

    client_addr_len = sizeof(client_address); 
    new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len); 
    if (new_sockfd < 0) 
     exit(1); 

    printf("accepted\n"); 


    int i; 

    for(i = 0; i < 11; i++) 
    { 
     // recieve messages from connected socket 
     printf("waiting\n"); 
     msg_len = read(new_sockfd, msg, MAX_DATA_SIZE); 
     if (msg_len < 1) 
     { 
      printf("no msg recieved\n");  
     } 
     else 
     { 
      printf("bytes recieved: %i\n", msg_len); 
     } 


     // send message to connected socket 
     msg_len = write(new_sockfd, got_msg, sizeof(got_msg)); 
     if (msg_len < 1) 
      printf("not sent\n"); 
     else 
      printf("%i bytes sent\n", msg_len); 
    } 


    // close connection 
    close(sockfd); 
    printf("socket closed. BYE! \n"); 


} 

Antwort

10

Im Server-Code, das Problem auf dieser Linie:

msg_len = read(sockfd, msg, MAX_DATA_SIZE); 

Du read auf sockfd aufrufen, aber Sie müssen read oder recv auf new_sockfd (die Fassung von accept() zurück) nennen. new_sockfd ist derjenige, der mit dem Client verbunden ist (sockfd wird verwendet, um weitere Verbindungen zu akzeptieren - zB wenn ein anderer Client eine Verbindung herstellt).

+0

Danke, dass das Problem gelöst hat !!! Und ja, das ist viel sinnvoller, aus dem neuen Socket-Dateideskriptor von accept() zu lesen. –

+2

Sie ignorieren auch die von read() und write() zurückgegebenen Zählerstände, abgesehen von der Überprüfung auf Fehler. Sie können das nicht tun: Sie müssen sie verwenden, um zu bestimmen, wie viele Daten tatsächlich gelesen oder geschrieben wurden. Sie können nicht davon ausgehen, dass Ihre Anfrage vollständig erfüllt wurde. – EJP

+0

EJP der Code berücksichtigt jetzt tatsächliche Bytes der gesendeten und empfangenen Nachrichten. Vielen Dank. –

-1

wird die Implementierung auf Strom oder Datagramm basiert?

Es gibt ein Problem mit Ihrem Arbeitsablauf. Der Server beginnt möglicherweise zu lesen, bevor der Client etwas sendet.

Da Client und Server getrennt sind, können Sie sich vorstellen, dass sie gleichzeitig ausgeführt werden. Direkt nachdem Ihre serverseitige Verbindungsanfrage "akzeptiert" wurde, kann es möglicherweise zu einem Handshake-Overhead oder Netzwerkverzögerungen kommen, die dazu führen, dass die Server-App zeitlich vorläuft, Daten extrahiert, aber Fehler findet (noch keine Daten empfangen). Sie können dies durch Hinzufügen von Ruhezustand im Servercode nach dem Akzeptieren der Verbindung ausprobieren, wobei der Client genügend Zeit haben sollte, um die Daten zu senden.

eine andere bessere Lösung ist es, die Datenwiederherstellung mit leerem Puffer oder asynchronem Lesen zu bewältigen.

+0

Es gibt kein Problem überhaupt mit der Server ruft 'read' vor dem Client sendet nichts. Der "Lese" -Ruf blockiert so lange, bis Daten verfügbar sind. "Noch keine Daten erhalten" ist ** nicht ** ein Fehler. – caf

+0

Und es gibt auch keinen Schlaf. – EJP

+0

Ich habe nur sleep() auf der Clientseite hinzugefügt, um das Problem zu finden, aber ich kann (und sollte nicht) sleep() verwenden, da der Zweck dieses Programms darin besteht, Paketumläufe zu messen. –

0

Sie sollten aus dem von accept zurückgegebenen Socket lesen.

Versuchen Sie read auf die socket zurück, die von accept zurückgegeben wird.

+0

Die vom Client gesendete Nachricht beginnt eindeutig mit einem Zeichen ".". – caf

+0

oh, ich habe den falschen Teil des Codes gesucht – stefanB

0

senden Seite:

while(!feof(fp)) 
{ 
    len=fread(buff,sizeof(char),MW,fp); 
    if(len==0) 
    { 
     //EOF 
     st=write(cd,&d,sizeof(int));  
     break; 
    } 
    else 
    { 
     st=write(cd,buff,len); 
    } 
} 
0

Empfängerseite:

while(1) 
    {  
     len=read(sd,buff,sizeof(buff)); 

     if(len==0) 
     { 
      //End of File receving.    

      break; 
     } 
     else  
     { 
      st=fwrite(buff,sizeof(char),len,fp); 

     } 
    }