C Winsock und Strings

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von toschk, 6. Juli 2007 .

Schlagworte:
  1. 6. Juli 2007
    So, mein Problem ist wenn ich einen String mit Winsock versende/empfange dann teilt er jedes Wort in einem Satz sodas jedes Wort in einer eigenen Zeile steht. Was kann ich dagegen machen?

    {bild-down: http://toschk.pytalhost.com/RR/konsole.gif}


    server.cpp:

    Code:
    #include <windows.h>
    #include <winsock2.h>
    #include <iostream>
    
    
    int startWinsock()
    {
     WSADATA wsa;
     return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    
    void startSockTest(long rc)
    {
     if(rc!=0){printf("Fehler: Winsock konnte nicht gestartet werden\n");}else{printf("Winsock gestartet...\n");}
    }
    
    void SockTest(SOCKET s)
    {
     if(s==INVALID_SOCKET){printf("Fehler: Socket konnte nicht geöffnet werden\n");}else{printf("Socket geoeffnet...\n");}
    }
    
    void bindTest(long rc)
    {
     if(rc==SOCKET_ERROR){printf("Fehler: Bind gescheitert, Fehlercode: %d\n",WSAGetLastError());}else{printf("Socket an Port gebunden...\n");}
    }
    
    void listenTest(long rc)
    {
     if(rc==SOCKET_ERROR){printf("Fehler: Listen konnte nicht ausgeführt werden, Fehlercode: %d\n", WSAGetLastError());}else{printf("Socket ist im Listen-Modus...\n");}
    }
    
    void connTest(SOCKET a)
    {
     if(a == INVALID_SOCKET){printf("Fehler: Verbindung kann nicht aufgebaut werden, Fehlercode: %d\n", WSAGetLastError());}else{printf("Verbindung wurde akzeptiert...\n");} 
    }
    /////////////////////////////////////////
    int main()
    {
     long rc = startWinsock();
     SOCKET acceptSocket = socket(AF_INET, SOCK_STREAM, 0);
     SOCKET connectedSocket;
     SOCKADDR_IN addr;
     
     memset(&addr,0, sizeof(SOCKADDR_IN));
     addr.sin_family = AF_INET;
     addr.sin_port = htons(5456);
     addr.sin_addr.s_addr = ADDR_ANY;
     rc = bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));
     rc = listen(acceptSocket, 10);
     
     connectedSocket = accept(acceptSocket, NULL, NULL);
    
     startSockTest(rc);
     SockTest(acceptSocket);
     bindTest(rc);
     listenTest(rc);
     connTest(connectedSocket);
     
     char text[100];
     char text2[100];
     while(rc!=SOCKET_ERROR)
     {
     rc = recv(connectedSocket,text, sizeof(text), 0);
     text[rc] = '\0';
     strcpy(text2, text);
     printf("%s\n", text2);
     }
     
     closesocket(acceptSocket);
     closesocket(connectedSocket);
     WSACleanup();
    system("PAUSE"); 
    return 0; 
    }
    /////////////////////////////////////////
    
    client.cpp

    Code:
    #include <windows.h>
    #include <winsock2.h>
    #include <iostream>
    using namespace std;
    
    int startWinsock()
    {
     WSADATA wsa;
     return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    
    void startSockTest(long rc)
    {
     if(rc!=0){printf("Fehler: Winsock konnte nicht gestartet werden\n");}else{printf("Winsock gestartet...\n");}
    }
    
    void SockTest(SOCKET s)
    {
     if(s==INVALID_SOCKET){printf("Fehler: Socket konnte nicht geöffnet werden\n");}else{printf("Socket geoeffnet...\n");} 
    }
    
    void connTest(long rc)
    {
     if(rc==SOCKET_ERROR){printf("Fehler: Connect gescheitert, Fehlercode: %d\n",WSAGetLastError());}else{printf("Verbindung aufgebaut...\n");}
    }
    /////////////////////////////////////////
    int main()
    {
     long rc = startWinsock();
     SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
     SOCKADDR_IN addr;
     
     memset(&addr,0,sizeof(SOCKADDR_IN));
     addr.sin_family = AF_INET;
     addr.sin_port = htons(5456);
     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
     rc = connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR));
     
     startSockTest(rc);
     SockTest(s);
     connTest(rc);
     char text2[100];
     char text[100];
     while(true){
     
     cin >> text2;
     strcpy(text, text2);
     send(s, text, sizeof(text), 0);
     }
     closesocket(s);
     WSACleanup();
     
    system("PAUSE"); 
    return 0; 
    }
    /////////////////////////////////////////
    
     
  2. 6. Juli 2007
    AW: C Winsock und Strings

    Hi !

    Code:
    [...]
    printf("%s\n", text2);
    [...]
    Versuch mal:
    Code:
    printf ("\'%s\'\n", text2);
    
    Dann sieht man genauer, was du empfaengst.

    Code:
    cin >> text2;
    strcpy(text, text2);
    send(s, text, sizeof(text), 0);
    Fehleranfaellig:
    1. strcpy -> strncpy
    2. sizeof (text) -> Wenn es ein Pointer ist, ist er nur 4 bzw. 8 bytes gross, dann sendet er nur 4 bzw. 8.
    Deshalb durch '100' ersetzen. Du solltest aber keine 'Magic Numbers' benutzen. Also am besten #define MAX_BUF 100, und dann immer 'MAX_BUF' benutzen ( bzw. MAX_BUF - 1 ).

    ---

    Es gibt 2 Moeglichkeiten, warum es nicht funktioniert.
    1. 'cin' liest jeweils nur 1 'Wort' ein, und dann geht die Funktion weiter
    2. TCP-Protokoll. Sendet die Daten zwar als Stream, und sie kommen in der richtigen Reihenfolge an, aber nicht wie sie als Pakete verschickt wurden:
    Beispiel:
    Client sendet ( in 1 Befehl, in 1 CharArray ):
    Server bekommt aber 3 Pakete:
    Das ist eine Eigenheit des TCP-Protokolls und kann mithilfe von Delimitern kontrolliert werden.

    Mfg,

    Kolazomai
     
  3. 10. Juli 2007
    AW: C Winsock und Strings

    das problem ist damit leider nicht behoben. Hab nen bisschen nach Delimitern gegoogelt aber leider brauchbares nix gefunden.
     
  4. 10. Juli 2007
    AW: C Winsock und Strings

    Mit Delimitern ist gemeint, dass du solange von der Tastatur einliest, bist das Zeichen \r oder \n ist. Die stehen ja für einen Zeilenumbruch, also Enter-Taste-gedrückt.

    Dann kannst du einfach alles schicken, was bis zum \r oder \n eingegeben wurde.
     
  5. 10. Juli 2007
    AW: C Winsock und Strings

    ja dachte ich mir schon. das problem ist das winsock die daten zerstückelt. ich übergib ja der send fuktionen nen vollständiges Array (String). nur kommt es nicht auf einmal an.
     
  6. 10. Juli 2007
    AW: C Winsock und Strings

    Hi!

    Deshalb brauchst ja auch einen Delimiter.
    Du empfaengst dann mitm Server so lange, bis der Delimiter kommt, und dann weisst du, was die ganze Message war. Das verhindert dann beides, sowohl, dass zu wenig, als auch, dass zu viel kommt.

    Beispiel:

    Der Delimiter ist '\n' ( Das ist haeufig der Fall, da man '\n' schwer schreiben kann ).

    Client sendet:
    Code:
    BEFEHL EINS\n
    Code:
    BEFEHL ZWEI\n
    Server empfaengt:
    Code:
    BEFEHL EINS\nBEFEHL ZWEI\n
    Jetzt einfach bei '\n' splitten, und schon hast du die Befehle, so wie sie gesendet wurden
    Du musst halt schaun, dass da auch ein '\n' ist, weil er sonst ja nicht splitten kann. Wenn es kein '\n' gibt, weisst du, dass der Befehl noch nicht vollstaendig empfangen wurde.

    Mfg,

    Kolazomai
     
  7. 10. Juli 2007
    AW: C Winsock und Strings

    gut klingt einleuchtend. mit welchen funktionen in verbindung mit winsock also send() und recv() stell ich das an. bei tastatureingaben benutzt man ja getline().
     
  8. 10. Juli 2007
    AW: C Winsock und Strings

    Hi !

    C Funktionen:
    strncat () -> An den Buffer, mit dem du was empfaengst, anfuegen
    strcspn () -> Schaun, ob Delimiter im Buffer
    strtok () -> Splitten

    In C++ geht das mit dem 'string' type bestimmt schoener.

    Mfg,

    Kolazomai
     
  9. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.