Problem mit Datenempfang bei Socket



  • Hallo zusammen,
    mein Problem ist das ich ein socket programmiert habe, um eine Kommunikation mit einem Laser herzustellen. Die Verbindung und das senden der Daten Funktioniert schon, aber ich kann keine Daten empfangen.

    Hier ist der Code:

    #include <iostream>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    //link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
    
    #define DEFAULT_BUFLEN 1024
    #define DEFAULT_PORT "2111"
    
    int main() {
        WSADATA wsaData;
        SOCKET ConnectSocket = INVALID_SOCKET;
        struct addrinfo *result = NULL,
                        *ptr = NULL,
                        hints;
        char *sendbuf = "0202020200000017734D4E206D4C527265717472696764617461203030323080";
        char recvbuf[DEFAULT_BUFLEN];
        int iResult;
        int recvbuflen = DEFAULT_BUFLEN;
        int a;
        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
        if (iResult != 0) {
            printf("WSAStartup failed: %d\n", iResult);
            return 1;
        }
    
        ZeroMemory( &hints, sizeof(hints) );
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
    
        // Resolve the server address and port
        iResult = getaddrinfo("192.168.0.1", DEFAULT_PORT, &hints, &result);
        if ( iResult != 0 ) {
            printf("getaddrinfo failed: %d\n", iResult);
            WSACleanup();
            return 1;
        }
    
        // Attempt to connect to an address until one succeeds
        for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
    
            // Create a SOCKET for connecting to server
            ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
                ptr->ai_protocol);
            if (ConnectSocket == INVALID_SOCKET) {
                printf("Error at socket(): %ld\n", WSAGetLastError());
                freeaddrinfo(result);
                WSACleanup();
                return 1;
            }
    
            // Connect to server.
            iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
            if (iResult == SOCKET_ERROR) {
                closesocket(ConnectSocket);
                ConnectSocket = INVALID_SOCKET;
                continue;
            }
            break;
        }
    
        freeaddrinfo(result);
    
        if (ConnectSocket == INVALID_SOCKET) {
            printf("Unable to connect to server!\n");
            WSACleanup();
            return 1;
        }
    
        // Send an initial buffer
        iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
        if (iResult == SOCKET_ERROR) {
            printf("send failed: %d\n", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        }
    
        printf("Bytes Sent: %ld\n", iResult);
    
        // shutdown the connection since no more data will be sent
        iResult = shutdown(ConnectSocket, SD_SEND);
        if (iResult == SOCKET_ERROR) {
            printf("shutdown failed: %d\n", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        }
    
        // Receive until the peer closes the connection
        do {
    
            iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
            if ( iResult > 0 ){
               printf("Bytes received: %d\n", iResult);
               std::cout << "Received data = " << recvbuf;
            }else if ( iResult == 0 ){
               printf("Connection closed\n");
            }else{
               printf("recv failed: %d\n", WSAGetLastError());
            }
    
        } while( iResult > 0 );
    scanf("%s",a);
        // cleanup
        closesocket(ConnectSocket);
        WSACleanup();
    
        return 0;
    }
    

    Als Ausgabe bekomme ich immer nur "Bytes Sent 64" und dann "Connection closed".
    Ich weis allerdings nicht wo der Fehler liegen könnte.
    Für jegliche Hilfe wäre ich sehr dankbar.
    MFG Fred



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (auch C++0x) in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Bei mir funktioniert der Code.
    Ich habe ihn übersetzt und konnte auf meinen Server verbinden.
    Den Server habe ich "test" senden lassen. Dein Programm gibt aus:

    Bytes Send: 64
    Bytes Received: 5
    Received data = test

    Es sieht also so aus, als ob bei dir der Server die Verbindung beendet.



  • Super Danke fürs Testen, hab schon gedacht ich steh auf dem schlauch und seh den Fehler nicht!!!
    Nochmals danke!



  • Hey Nochmal,
    ich habe den Fehler jetzt mit Wireshark entdeckt. dadurch ist aber ein neues Problem entstanden. Ich muss die Daten direkt als HEX in dem TCP-Protokoll verschicken. D.h. wenn ich die Daten normal verschicke werden diese in dem Protokoll in HEX übersetzt und ergeben so andere Werte. Z.B. der Wert 02(steht für STX senden von daten) hat kein einzelnes Zeichen zum verschicken und wird somit in 0=30 und 2=32 umgewandelt!
    Meine Frage ist deshalb, wie kann ich mit dem socket direkt Daten in das TCP-Protokoll bekommen?
    Wäre echt super wenn mir jemand helfen könnte.
    mfg fred



  • Du versendetst doch schon als TCP.
    Wenn du die daten in hexadezimal amgewandelt haben mußt.

    Hier ist das Ergebnis immer 8 zeichen lang:

    char* hex_output(unsigned long val)
    {
    
    	long reste[9];
    	char *str = new char[9];
    	for (long i=0; i < 8; i++)
        {
    
    		long help = reste[i]= val% 16;
            val /= 16;
        }
    	for(long i=8-1; i>-1; i--)
        {
            switch(reste[i])
            {
    		case 0: {str[7-i] = '0'; break;}
    		case 1: {str[7-i] = '1'; break;}
    		case 2: {str[7-i] = '2'; break;}
    		case 3: {str[7-i] = '3'; break;}
    		case 4: {str[7-i] = '4'; break;}
    		case 5: {str[7-i] = '5'; break;}
    		case 6: {str[7-i] = '6'; break;}
    		case 7: {str[7-i] = '7'; break;}
    		case 8: {str[7-i] = '8'; break;}
    		case 9: {str[7-i] = '9'; break;}
    		case 10: {str[7-i] = 'A'; break;}
    		case 11: {str[7-i] = 'B'; break;}
    		case 12: {str[7-i] = 'C'; break;}
    		case 13: {str[7-i] = 'D'; break;}
    		case 14: {str[7-i] = 'E'; break;}
    		case 15: {str[7-i] = 'F'; break;}
            }
        }
    str[8] = '\0';
    return str;
    }
    

    Hier ist das Ergebnis genau so lang wie nötig:

    char* hex_output2(unsigned long val)
    {
    
    	int count = 0;
    	unsigned long  val_help = val;
    	while(val_help != 0)
    	{
            val_help /= 16;
    		count++;
        }
    
    	long *reste = new long[count];
    	char *str = new char[count+1];
    	for (long i=0; i < count; i++)
        {
    
    		long help = reste[i]= val% 16;
            val /= 16;
        }
    	for(long i=count-1; i>-1; i--)
        {
            switch(reste[i])
            {
    		case 0: {str[count-1-i] = '0'; break;}
    		case 1: {str[count-1-i] = '1'; break;}
    		case 2: {str[count-1-i] = '2'; break;}
    		case 3: {str[count-1-i] = '3'; break;}
    		case 4: {str[count-1-i] = '4'; break;}
    		case 5: {str[count-1-i] = '5'; break;}
    		case 6: {str[count-1-i] = '6'; break;}
    		case 7: {str[count-1-i] = '7'; break;}
    		case 8: {str[count-1-i] = '8'; break;}
    		case 9: {str[count-1-i] = '9'; break;}
    		case 10: {str[count-1-i] = 'A'; break;}
    		case 11: {str[count-1-i] = 'B'; break;}
    		case 12: {str[count-1-i] = 'C'; break;}
    		case 13: {str[count-1-i] = 'D'; break;}
    		case 14: {str[count-1-i] = 'E'; break;}
    		case 15: {str[count-1-i] = 'F'; break;}
            }
        }
    str[count] = '\0';
    return str;
    }
    

    Hab ich mal so auf die Schnelle zusammengefrickelt. Geht bestimmt eleganter, aber sollte funktionieren.



  • Wenn du die Funktionen verwendest, denk daran die nötigen "delete" einzubauen!



  • Hallo,
    vielen dank für den Code kann ich bestimmt noch gut gebrauchen!
    Du hast recht ich schick ja sc´hon tcp und der wandelt das ja in Hex um.
    Mein Problem ist das ich STX nicht so schreiben kann das es in dem tcp protokoll als 02 umwandelt!!!!
    Auf der Liste : http://www.torsten-horn.de/techdocs/ascii.htm
    kann man Zeichen wie NULL oder STX erkennen. Diese muss ich so in c++ verschicken das ich in dem telegramm den richtigen hex-wert habe!
    Problem ist das bei den gesendeten daten alle buchstaben oder zeichen einzeln geschickt werden!ich habe schon sachen wie <STX>, ´STX´,^B,{STX} oder (STX) schon probiert.
    Ich habe einfach gerade keine Idee wie das gehen soll.



  • mal ganz anders: der Hersteller des LASERs (bzw. der Steuereinheit) wird doch bestimmt eine library/interface zur Kommunikation/Steuerung anbieten? Oder ist das ein Eigenbau?



  • Hey,
    ja der Laser hat ein Programm mit Bedienoberfläche mit dem man Daten austauschen kann, allerdings komm ich da nicht an hilfreiche Code-teile ran. Der Laser ist von der Firma Sick. Diese stellt die Hardware zur Verfügung aber machen keine Software(so wurde mir das gesagt!). Ich habe dort auch schon öffters nach Hilfe gefragt aber keiner konnte mir da genau helfen.
    Das Datenpacket was ich verschicken muss hat folgenden Aufbau:
    {STX}{STX}{STX}{STX}{LEN4Byte}sMN mLRreqtrigdata oo2o€
    Bin die ganze Zeit am basteln wie das funktionieren könnte und habe gehofft das mir hier vielleicht jemand helfen kann.

    MFG
    fred



  • Du musst einfach wissen, ob Du wirklich
    char *s = "{STX}";

    send(... , s, 4, ...);

    verschicken musst, oder aber
    int x = 2; // weil Du geschrieben hast, STX entspricht dem Wert 2
    char *p = (char*) &x;

    send(..., p, sizeof(int), ...);

    im letzten Fall musst Du Dir evtl. noch Gedanken über Byte-Ordering (little endian oder big endian) machen.

    Oder vielleicht tatsächlich

    char *s = "02"; //oder "0002" oder "0x02"

    Das geht für mich nämlich nicht eindeutig aus Deinen Beschreibungen hervor.



  • Ich muss STX verschicken, allerdings wenn ich das so verschicke liest das Programm jeden buchstaben einzeln ein und sendet dann im TCP-Protokoll statt
    02, schickt er 53 54 58.
    D.h. Mein Server kommuniziert nicht mit mir, weil das falsche gesendet wird!
    Ich habe jetzt aber eine kleine Lösung dafür gefunden.
    Wenn ich \2 verschicke kommt auch der richtige Wert im TCP-Protokoll an.
    Problem jetzt ist das die Länge der Sendedaten in dem TCP-Protokoll,denn diese soll so aussehen:
    00 00 00 17
    doch wenn ich \0 eingebe(um im Protokoll 00 zu bekommen) bricht er das sendepacket sofort ab, weil er denk das es zu ende ist!
    Kennt da vielleicht jemand nen weg wie man das umgehen kann!!!

    Meine Sendecode sieht so aus

    char *sendbuf= "\2\2\2\2\0\0\0\x17sMN mLRreqtrigdata 0020€";
    ....
    send(Connectsocket, sendbuf, (int)strlen(sendbuf), 0);

    fred



  • fred friedenberg schrieb:

    Meine Sendecode sieht so aus

    char *sendbuf= "\2\2\2\2\0\0\0\x17sMN mLRreqtrigdata 0020€";
    ....
    send(Connectsocket, sendbuf, (int)strlen(sendbuf), 0);

    strlen(sendbuf) gibt hier natürlich nicht die richtige Länge zurück. Ermittel die Länge selbst, indem Du sendbuf nach '€' durchsuchst, oder gib gleich den richtigen Wert als Literal an.



  • Ja klar, danke, da hät ich auch selber drauf kommen müssen!
    Habe das Datenpaket jetzt endlich zusammen.
    Danke an alle die mitgeholfen haben.
    gruß
    fred


Anmelden zum Antworten