Winsock2 ungewöhnliche Ausgaben nach Datenversand!



  • Hallo liebe Community!

    Ich programmiere gerade etwas mit WinSock und will gerade den Grundstein für eine etwas aufwendige Anwendung legen!

    Allerdings bin ich auf ein Problem gestoßen!
    Also ich verwende WinSock2 und versende Daten über TCP die aus einer Datei glesen werden und auf einem anderen Computer in eine Datei geschrieben werden!

    Allerdings produzieren die Programme unsinnige Ausgaben!

    Hier die Quelltexte des Servers sowie Clienten:

    Server:(empfängt Daten)

    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int startWinsock(void);
    
    int main()
    {
    
    	long rc;
    	SOCKET acceptSocket;
    	SOCKADDR_IN addr;
    	SOCKET connectedSocket;
    	FILE *f;
    	char daten[2048];
    
    	rc= startWinsock();
    
    	if(rc != 0)
    		{
    			printf("Fehler: startWinsock(); Fehler-Code: %d\n", rc);
    
    			return 1;
    	}
    
    	else
    		printf("WinSock gestartet!\n");
    
    	 acceptSocket = socket(AF_INET, SOCK_STREAM, 0);
    
    	 if(acceptSocket == INVALID_SOCKET)
    		 {
    			 printf("Fehler der Socket konnte nicht erstellt werden!\n");
    			 printf("Fehler-Code: %d\n", WSAGetLastError());
    			 return 1;
    	     }
    
    	 else
    		 printf("Socket wurde erstellt!\n");
    
    	 memset(&addr, 0, sizeof(SOCKADDR_IN));
    	 addr.sin_family = AF_INET;
    	 addr.sin_port = htons(9999);
    	 addr.sin_addr.s_addr = ADDR_ANY;
    
    	 rc= bind(acceptSocket, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN));
    
    	 if(rc == SOCKET_ERROR)
    		 {
    			 printf("Fehler bind(); Fehler-Code: %d\n", WSAGetLastError());
    			 return 1;
    		 }
    
    	 else
    		 printf("Socket an Port: 9999 gebunden!\n");
    
    	 rc= listen(acceptSocket, 10);
    
    	 if(rc == SOCKET_ERROR)
    		 {
    			 printf("Fehler listen(); Fehler-Code: %d\n!", WSAGetLastError());
    			 return 1;
    	     }
    
    	 else
    		 printf("Listen(); gestartet!\n");
    
    	 connectedSocket= accept(acceptSocket, NULL, NULL);
    
    	 if(connectedSocket == INVALID_SOCKET)
    		 {
    			 printf("Fehler: accept(); Fehler-Code: %d!\n", WSAGetLastError());
    			 return 1;
    		 }
    
    	 else
    		 printf("Neue Verbindung wurde akzeptiert!\n");
    
         rc= recv(acceptSocket, daten, sizeof(daten), 0);
    
    	 f = fopen("FromServer.txt", "w");
    
    	 fputs(daten, f);
    
         system("PAUSE");
    
    	 return 0;
    
    }
    
    int startWinsock(void)
    
    {
    
      WSADATA wsa;
    
      return WSAStartup(MAKEWORD(2,0),&wsa);
    
    }
    

    Client:(versendet Daten)

    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    //Prototypen
    
    int startWinsock(void)
    
    {
    
      WSADATA wsa;
    
      return WSAStartup(MAKEWORD(2,0),&wsa);
    
    }
    
    int main()
    
    {
    
      long rc;
      SOCKET s;
      SOCKADDR_IN addr;
    
      FILE *f;
      char file_name[255];
      char daten[2048];
    
      rc=startWinsock();
    
      if(rc!=0)
    
      {
    
        printf("Fehler: startWinsock, fehler code: %d\n",rc);
    
        return 1;
    
      }
    
      else
    
      {
    
        printf("Winsock gestartet!\n");
    
      }
    
      s=socket(AF_INET, SOCK_STREAM, 0);
    
      if(s == INVALID_SOCKET)
          {
              printf("Der Socket konnt nicht erstellt werden:\n");
              printf("Fehler-Code: %d\n", WSAGetLastError());
              return 1;
          }
    
      else
          {
              printf("Socket erstellt!\n");
          }
    
      memset(&addr,0,sizeof(SOCKADDR_IN));
    
      addr.sin_family = AF_INET;
      addr.sin_port = htons(9999);
      addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
      rc= connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR));
    
      if(rc==SOCKET_ERROR)
    
    {
    
      printf("Fehler: connect gescheitert, fehler code: %d\n",WSAGetLastError());
      system("PAUSE");
      return 1;
    
    }
    
    else
    
    {
    
      printf("Verbunden mit 127.0.0.1..\n");
    
    }
    
      printf("Welche Datei wollen Sie versenden: \n");
      scanf("%s", file_name);
    
      f = fopen(file_name, "r");
    
      if(f == NULL)
          {
              printf("Fehler beim Lesen!\n");
              exit(0);
          }
    
      else
          {
              while( fgets(daten, sizeof(daten), f) != 0)
                  {
                  rc = send(s, daten, sizeof(daten), 0);
                  }
          }
    
      system("PAUSE");
    
      return 0;
    
    }
    

    Die Ausgaben sind allenfalls kyrillisch, vielleicht kennt ein Programmieren mit Winsock Erfahrung das Problem?

    Danke im Vorraus!

    EOF



  • *wiederbeleb*



  • Zwei Sachen beim überfliegen: Überprüf beim Server mal den Rückgabewert von "recv". Wenn gesendet wird, kann es sein, dass erst nur die Hälfte ankommt und der Rest später. Zweitens: "fputs" erwartet einen String. Ich weiß nicht, welche Daten du rüberschickst, aber sie sind so wahrscheinlich nicht null-terminiert oder könnten eine null mittendrin enthalten.



  • Also ich hab den Read-Modus für die Datei, jetzt zusätzlich auf Binär gesetzt!

    f = fopen(file_name, "rb");
    

    Das hat nichts gebracht gleiche Ausgaben!

    Dann habe ich den Rückgabewert der Funktion send(); überprüft,aslo in rc steht 4!
    Dann habe ich die Größe der Datei, welche in der Struktur dataStat steht undmit dataStat.st_size abgefragt wird überprüft : 16!

    printf("Rückgabewert: %d\n", rc);
      printf("Dateigröße: %d\n", dataStat.st_size);
    

    In dein Eigenschaften der Datei steht:

    Größe: 16 Bytes

    Größe auf Datenträger 4,00 KB(4.096 Bytes)

    Erklärmir einer das Problem, bitte!



  • char daten[2048];
    ...
    while( fgets(daten, sizeof(daten), f) != 0)
    {
        rc = send(s, daten, sizeof(daten), 0);
    }
    

    Deine Datei ist 16 Bytes groß und du schickst 2048 - woher soll der Server wissen, wie groß die Datei ist, bzw welche der 2048 (oder mehr) Bytes zu der Datei gehören? Du könntest entweder die Dateigröße vorneweg schicken und/oder nur den tatsächlichen Datei-Inhalt verschicken.



  • Ich habe den Speicher (das habe ich vergessen zu erwähnen) dynamisch zugewiesen:

    char *daten = NULL;
    

    Ich habe jetzt eine andere Methode versucht:

    Zum Versenden:

    {
    
    		  char *daten = NULL;
    
              stat(file_name, &dataStat);
    		  daten = malloc(dataStat.st_size);
    
    		  while( read(handle, daten, sizeof(dataStat.st_size)) != 0)
    			  {
    		      printf("Daten[]: %s!\n", daten);
    			  rc = send(s, daten, sizeof(daten), 0);
    			  }
    	  }
    

    Folgendes Ergebnis bekomme ich in der Variable daten:

    Daten[]: Tomx☺¶!
    Daten[]: istx☺¶!
    Daten[]: schx☺¶!
    Daten[]: wul!x☺¶!

    Die Original Zichenkett in der Originaldatei, welche eine Textdatei ist, lautet:
    [/quote]Tom ist schwul![/quote]

    Zum empfangen habe ich folgenden Source geschrieben:

    rc= recv(acceptSocket, daten, sizeof(daten), 0);
    	 printf("Daten[]: %s!\n", daten);
    
    	 handle = open("FromServer.txt", O_BINARY|O_CREAT);
    
    	 write(handle, &daten, sizeof(daten));
    

    Wenn ich die Daten im Server ausgebe erhalte ich allerdings nur noch folgenden Zeichenkette:

    (null)

    Mein anliegen ist es jede Datei jedes beliebigen Datentyps so zu verschicken das sie Original auf einem anderem Rechner reproduziert wird!

    Allerdings gelingt mir das nicht!

    Kann mir nicht jemand die Funktion oder den Code-Schnipsel für mein Anliegen programmieren!

    Dann macht es vielleicht Klick!

    Danke im Vorraus!



  • @LØRdSe: Bist Du Tom?



  • { 
    
              char *daten = NULL; 
    
              stat(file_name, &dataStat); 
              daten = malloc(dataStat.st_size); 
    
              while( read(handle, daten, sizeof(dataStat.st_size)) != 0) 
                  { 
                  printf("Daten[]: %s!\n", daten); 
                  rc = send(s, daten, sizeof(daten), 0); 
                  } 
          }
    

    sizeof(daten) ist auf üblichen 32 bit system 4!!!
    Ist das was Du willst? Vermutlich nicht.



  • simon.gysi schrieb:

    @LØRdSe: Bist Du Tom?

    Nein Tom ist mein bester Freund(natürlich rein platonisch)!
    Und er ist nicht schwul nur jeder muss ein Opfer bringen!

    So bitte Back2Topic, ich würde das Problem gerne lösen!



  • werte doch mal die rückgabe werte der send(..) und recv(..) funktionen aus.. dann hättest Du bemerkt, dass da ein fehler mit sizeof(daten) sein muss...

    benutzt du einen Debugger?

    Simon



  • So bitte Back2Topic, ich würde das Problem gerne lösen!

    Grundlagen lernen.
    Simon



  • Nein ich benutze keinen Debugger!

    Ich habe festgestllet das der Rückgabewert der Funktion recv() -1 ist!
    Und deiner Meinung nach liegt das an dem sizeof(daten), allerdinsg habe ich das jetzt in:

    sizeof(dataStat.st_size);
    

    geändert!

    EDIT:

    Ich dachte recv(); ist ein Blocking Call allerdings gebe ich in meinem Server Programm den Rückgabewert der Funktion recv(); aus dieser wird allerdings schon ausgegeben bevor ich überhaupt eine Datei gesendet hab!

    @Simon diese Antworten:

    Grundlagen lernen!

    halte ich für ziemlich unproduktiv!
    Vielleicht würdest du mir mit dem funktionierendem Code-Schnipsel und einer kleinen Erklärung dazu viel mehr helfen!

    Also bitte setze es dochmnal fürmich um!



  • simon.gysi schrieb:

    Grundlagen lernen.

    Dem schließe ich mich an. Wenn du noch nicht mal "sizeof" verstehst, solltest du noch ein paar einfachere Anwendungen schreiben oder Tutorials durchackern.



  • 1. Tip: Benutze den Debugger!
    2.

    Ich habe festgestllet das der Rückgabewert der Funktion recv() -1 ist!
    Und deiner Meinung nach liegt das an dem sizeof(daten), allerdinsg habe ich das jetzt in:

    Nein, das war nicht meine Meinung.

    Ob recv(..) blocking ist oder nicht hängt übrigens mit dem Socket zusammen.
    Bei Dir ist es allerdings blocking.

    recv(..) soll man in einer Schleife benutzen und den Rückgabe beachten!
    Smion



  • Korrigiert mich wenn ich mich irre!
    Aber eigentlich bin ich mir ziemlich sicher das sizeof() mir die Anzahl Bytes liefert die für eine Variable reserviert wird!

    Also was genau is das Problem?

    Was mich stutzig macht:
    Alleine dieser Code-Schnipsel produziert unsinnige Ausgaben:

    Client:

    strcpy(file_name, "Hallo!");
      send(s, file_name,6,0);
    

    Server:

    rc= recv(acceptSocket, daten, 6, 0);
       printf("%s", daten);
    

    Da kann doch jetzt nix falsch dran sein!



  • LØRdSe schrieb:

    Korrigiert mich wenn ich mich irre!
    Aber eigentlich bin ich mir ziemlich sicher das sizeof() mir die Anzahl Bytes liefert die für eine Variable reserviert wird!

    Also was genau is das Problem?

    Ja du liegst sowas von falsch des gibts gar net -> Beispiel:

    char		*test;
    
    	printf("vor malloc:%i", sizeof(test));	//= 4
    	test = malloc(46214);
    	printf("nach malloc:%i", sizeof(test));	//= 4
    	free(test);
    	printf("ich habs doch gleich gesagt!");
    

    *** aber! ***

    char		doguggste[123];
    
    	printf("ach so:%i", sizeof(doguggste));	//= 123
    

    gib das mal ein und staune



  • Da hast Du allerdings recht.
    Allerdings ist deine Variable ein Pointer (und dessen Grösse wird zurückgegeben, eben vermutlich 4).
    Und der Pointer zeigt auf Memory, dessen Grösse aber der Programmierer verwalten muss.

    Für detailiertere Erklärungen schlage ich vor, dass Du mal bei MSDN nachliest.

    Gruss Simon



  • Und wenn bei Fall 2 von doguggste die Variable (eine Array Variable) weitergereicht wird, dann geht sizeof wieder nicht so wie Du's gerne hättest...
    Simon



  • Also bei dem Winsock Ding ist es ja so, daß oft u_char Strings gesendet und/oder empfangen werden. Wenn du sendest solltest du schon wissen was du sendest, also ist dir die Länge des SendStrings bekannt. Wenn du empfängst und die Daten in einem Buffer (z.B. Char array oder mit malloc zugewiesener Speicher) gespeichert werden weisst du nur am Rückgabewert von recv wieviele Daten wirklich empfangen wurden. Strlen oder ähnliches versagt da, weil du ja möglöicherweise Daten empfängst die auch gewollt '\x00' enthalten. Das ist im groben die Funktionsweise von send/recieve.



  • Was mich stutzig macht:
    Alleine dieser Code-Schnipsel produziert unsinnige Ausgaben:

    Client:

    strcpy(file_name, "Hallo!");
      send(s, file_name,6,0);
    

    Server:

    rc= recv(acceptSocket, daten, 6, 0);
       printf("%s", daten);
    

    Da kann doch jetzt nix falsch dran sein!



  • LØRdSe schrieb:

    Was mich stutzig macht:
    Alleine dieser Code-Schnipsel produziert unsinnige Ausgaben:

    Client:

    strcpy(file_name, "Hallo!");
      send(s, file_name,6,0);
    

    Server:

    rc= recv(acceptSocket, daten, 6, 0);
       printf("%s", daten);
    

    Da kann doch jetzt nix falsch dran sein!

    rc= recv(acceptSocket, daten, 6, 0);
       daten[rc] = '\0'; // <-------------
       printf("%s", daten);
    

    🙄 🙄 🙄


Anmelden zum Antworten