2010-08-11 7 views
1

Hé les gars, voici mon code.Données de socket étranges C++

int main() { 

    char buffer[BUFSIZE]; 

    // define our address structure, stores our port 
    // and our ip address, and the socket type, etc.. 
    struct sockaddr_in addrinfo; 
    addrinfo.sin_family = AF_INET; 
    addrinfo.sin_port = htons(PORT); 
    addrinfo.sin_addr.s_addr = INADDR_ANY; 


    // create our socket. 
    int sock; 
    if ((sock = socket(addrinfo.sin_family, SOCK_STREAM, 0)) < 0) { 
     cout << "Error in creating the socket."; 
    } 

    // bind our socket to the actual adress we want 
    if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) { 
     cout << "Error in binding."; 
    } 

    // open the socket up for listening 
    if (listen(sock, 5) != 0) { 
     cout << "Error in opening listener."; 
    } 
    cout << "Waiting for connections...." << endl; 

    char *msg = "Success! You are connected.\r\n"; 

    // continuously accept new connections.. but no multithreading.. yet 
    while(1) { 

     struct sockaddr_in client_addr; 
     socklen_t sin_size = sizeof(client_addr); 

     if(int client = accept(sock, (struct sockaddr*)&client_addr, &sin_size)) { 
      cout << "Recived new connection from " << inet_ntoa(client_addr.sin_addr) << endl; 
      send(client, msg, strlen(msg), 0); 
      while(1) { 
       send(client, buffer, recv(client, buffer, BUFSIZE, 0), 0); 

       cout << buffer << endl; 
       strcpy(buffer, ""); 
      } 

     } else { 
      cout << "Error in accepting new connection." << endl; 
     } 

    } 

    close(sock); 
    return 0; 
} 

Maintenant, je suis très nouveau aux prises, Im juste une sorte d'essayer d'obtenir une sensation pour eux mais j'ai une certaine expérience avec les sockets en PHP. J'utilise telnet via putty sur ma machine linux pour tester cela, je ne sais pas si cela cause des problèmes mais le serveur sort des caractères étranges et je ne sais pas pourquoi. Je pense que cela a quelque chose à voir avec le tampon, mais je ne suis pas vraiment sûr. Je peux envoyer des choses comme "salut" au serveur via telnet et il les sort très bien et me les renvoie mais quand j'envoie des choses comme "hoobla" ça commence le truc funky. Toute suggestion serait utile!

Merci d'avance!

Répondre

16

Vous obtenez des déchets imprimés car recv ne met pas fin à votre tampon.

La section importante dans le code ci-dessous:

int num = recv(client,buffer,BUFSIZE,0); 
if (num < 1) break; 

send(client, ">> ", 3, 0);  // <<-- Nice to have. 
send(client, buffer, num, 0); 

buffer[num] = '\0';   // <<-- Really important bit! 

if (buffer[num-1] == '\n')  // <<-- Nice to have. 
    buffer[num-1] = '\0';  // <<-- Nice to have. 

cout << buffer << endl; 

qui mettra fin à bien votre tampon avant d'essayer de l'imprimer, ainsi que de retirer la nouvelle ligne de fuite si elle est présente (et permettre au client de faire la distinction entre l'entrée et écho des lignes).

Celui-ci (un programme complet) fonctionne un peu mieux:

using namespace std; 
#include <iostream> 
#include <sys/socket.h> 
#include <arpa/inet.h> 

#define BUFSIZE 1000 
#define PORT 1234 

int main() { 
    char buffer[BUFSIZE]; 

    // define our address structure, stores our port 
    // and our ip address, and the socket type, etc.. 
    struct sockaddr_in addrinfo; 
    addrinfo.sin_family = AF_INET; 
    addrinfo.sin_port = htons(PORT); 
    addrinfo.sin_addr.s_addr = INADDR_ANY; 

    // create our socket. 
    int sock; 
    if ((sock = socket(addrinfo.sin_family, SOCK_STREAM, 0)) < 0) { 
     cout << "Error in creating the socket."; 
     return -1; 
    } 

    // bind our socket to the actual adress we want 
    if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) { 
     cout << "Error in binding."; 
     return -1; 
    } 

    // open the socket up for listening 
    if (listen(sock, 5) != 0) { 
     cout << "Error in opening listener."; 
     return -1; 
    } 

    char *msg = "Success! You are connected.\r\n"; 

    // continuously accept new connections.. but no multithreading.. yet 
    while(1) { 
     cout << "Waiting for connections...." << endl; 

     struct sockaddr_in client_addr; 
     socklen_t sin_size = sizeof(client_addr); 

     if(int client = 
      accept(sock, (struct sockaddr*)&client_addr, &sin_size)) 
     { 
      cout << "Recieved new connection from " 
       << inet_ntoa(client_addr.sin_addr) << endl; 
      send(client, msg, strlen(msg), 0); 
      while(1) { 
       int num = recv(client,buffer,BUFSIZE,0); 
       if (num < 1) break; 
       send(client, ">> ", 3, 0); 
       send(client, buffer, num, 0); 

       buffer[num] = '\0'; 
       if (buffer[num-1] == '\n') 
        buffer[num-1] = '\0'; 
       cout << buffer << endl; 
       strcpy(buffer, ""); 
      } 
     } else { 
      cout << "Error in accepting new connection." << endl; 
     } 
    } 
    close(sock); 
    return 0; 
} 

Du côté client:

$ telnet 127.0.0.1 1234 
Trying 127.0.0.1... 
Connected to 127.0.0.1. 
Escape character is '^]'. 
Success! You are connected. 
hello 
>> hello 
my name is pax 
>> my name is pax 
and you? 
>> and you? 
<CTRL-D> 
Connection closed by foreign host. 

et, du côté du serveur:

$ ./testprog 
Waiting for connections.... 
Recived new connection from 127.0.0.1 
hello 
my name is pax 
and you? 
Waiting for connections.... 
+0

ok, donc recv retourne réellement la taille de l'octet qu'il contient? –

+0

Oui, ou -1 en cas d'erreur ou 0 si l'autre extrémité ferme la connexion, que le code traite également ici. – paxdiablo

1

Le problème est que buffer n'est pas garanti pour contenir un caractère nul de fin de chaîne. Ajoutez la ligne buffer[BUFSIZE-1] = '\0' juste avant votre cout << buffer.

Encore mieux, en réalité enregistrer combien d'octets ont été reçus, et utiliser cette information pour déterminer si vous avez dépassé votre tampon.

+0

hmm I comprendre ce que vous dites à propos du caractère nul. Mais cela ne semble pas fonctionner. Je reçois toujours des trucs étranges pour la sortie. Je ne serais sûrement pas déborder mon tampon var avec une chaîne de quatre lettres, je le ferais? –

+1

vous devez utiliser la valeur de retour de 'recv' pour stocker l'octet nul, sinon un recv de" hello "suivi d'un autre de" x "vous donnera" xello "(plus tout garbage est _already_ dans le tampon au-delà de la cinquième octet (jusqu'à la fin) dans les deux cas). – paxdiablo