TCP Chat



  • verrate mir mal WANN bei dir das break in deiner While(true) aufgerufen wird .... du hast das event zwar erzeugt aber es wird nie bedient ...

    mal abgesehen davon, dein recv liefert entweder anzahl bytes oder 0 wenn verbindung getrennt oder -1 wenn fehler .... du solltest mal ne fehlerkontrolle einbauen und nicht einfach davon ausgehen das die verbindung schon irgendwie hinhaut.

    könntest du eventuell auch ein paar auszuüge aus dem client servieren ? weil das scheint nur der server zu sein oder irre ich mich ?



  • Ceos schrieb:

    verrate mir mal WANN bei dir das break in deiner While(true) aufgerufen wird .... du hast das event zwar erzeugt aber es wird nie bedient ...

    mal abgesehen davon, dein recv liefert entweder anzahl bytes oder 0 wenn verbindung getrennt oder -1 wenn fehler .... du solltest mal ne fehlerkontrolle einbauen und nicht einfach davon ausgehen das die verbindung schon irgendwie hinhaut.

    könntest du eventuell auch ein paar auszuüge aus dem client servieren ? weil das scheint nur der server zu sein oder irre ich mich ?

    Ein chat hat ja die Eigenschaft in zwei Richtungen zu funktionieren, da es nicht geklappt hat, probiere ich jetzt erst mal die eine Richtung. Das event wird gesetzt wenn man exit eingibt. Eine Eingabe beim Empfänger gibt es aber halt noch nicht bzw. ich hab sie wieder raus genommen.
    Anbei der Sender, der auch das mit dem exit zeigt.

    sender

    #include <stdio.h>
    #include <winsock2.h>
    #include <iostream>
    #include <string>
    #include <conio.h>
    #include <fstream>
    #include "ic.hpp"
    using namespace std;
    // Namespace der Konsolenklasse zugänglich machen
    using namespace ic;
    
    // --- Initialisierungen --------------
    WSADATA stWSAData; // returned from WSAStartup
    WORD wVersionRequested; // requested WInsock Version
    SOCKET hSock; // socket handle created
    SOCKADDR_IN receiver; // socket address of receiver
    SOCKADDR_IN local; // local socket address
    int bRet(0);
    
    // char *buffer = "Hallo Welt"; // Testdata
    string buffer;
    // int buffer_size = strlen(buffer); // Size of Testdata
    int nRet; // Returncode
    HANDLE hThread;
    DWORD dwThreadId;
    char buffer_empfangen[1000]; // Empfangspuffer
    int buffer_size = 1000; // Grösse des Empfangspuffers
    int dwSenderSize; // size of socket address of sender
    int nByte; // Anzahl empfangener Bytes
    // CRITICAL_SECTION CS;
    // Hande für das Event
    HANDLE hEvent;
    // Stream für die Dateiausgabe
    ofstream Datei;
    SOCKET hClSock; // client socket handle returned form accept()
    
    DWORD WINAPI ThreadProc( LPVOID lpParam ){
    // --- Daten empfangen ----------------
    
    while(true){
    // ---- set listen mode ------------------------
    nRet = listen(hSock,SOMAXCONN);
    
    // --- accept connection -----------------------
    hClSock = accept(hSock,(SOCKADDR *)&receiver,(int*)sizeof(receiver));
    
    // --- receive some Bytes blocking ! ----------
    nByte = recv(hClSock,buffer_empfangen,buffer_size,0);
    	// Ausgaben
    	if(nByte > 0){
    
    		// Am ende die Null anhängen, da sonst mist ausgegeben wird
    		// WICHTIG strlen missachtet die \0 !!!
    		//buffer_empfangen[nByte] = 0;
    
    		// Textfarbe mit der Konsolenklasse auf rot setzen
    		con.setTextColor(FG_RED);
    		// Ausgabe der IP und Portnummer
    		cout << inet_ntoa(receiver.sin_addr) << ":" << ntohs(receiver.sin_port) << endl;
    		// In Datei schreiben
    		Datei << inet_ntoa(receiver.sin_addr) << ":" << ntohs(receiver.sin_port) << endl;
    		// Ausgabe der übertragennen Daten
    		cout << buffer_empfangen << endl;
    		// In Datei schreiben
    		Datei << buffer_empfangen << endl;
    	}
    	// Wenn das Event gesetzt wird, verlasse die Schleife
    	if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) break;
    }
    return 0;
    }
    
    int main(){
    
    con.setTitle(TEXT("UDP Chat"));
    // --- Wer bin ich ? ------------------
    cout << "UDP Sender ..." << endl << "Beenden durch Eingabe von exit" << endl;
    
    // --- Winsock initialisieren ---------
    wVersionRequested = MAKEWORD( 2, 0 ); // Version 2.0
    nRet = WSAStartup(wVersionRequested,&stWSAData);
    // Fehlerabfrage
    if(nRet < 0){
    	cout << "Fehler bei WSAStartup";
    }
    
    // --- Socket erzeugen ----------------
    hSock = socket(AF_INET,SOCK_STREAM,0);
    	if(INVALID_SOCKET == hSock){
    		return 1;
    	}
    
    // --- Socket binden ------------------
    local.sin_family = PF_INET;
    local.sin_port = htons((short)4711); // meine Portnummer
    local.sin_addr.s_addr = inet_addr("127.0.0.1"); // meine IP Adresse
    bRet = bind(hSock,(SOCKADDR *)&local,sizeof(local));
    // Fehlerabfrage
    if(bRet == SOCKET_ERROR) cout << ::WSAGetLastError();
    
    // --- Zieladresse setzen -------------
    receiver.sin_family = PF_INET;
    receiver.sin_port = htons((short)4712); // Zielport
    // receiver.sin_addr.s_addr = inet_addr("127.0.0.1"); // Ziel IP Adresse
    receiver.sin_addr.s_addr = inet_addr("127.0.0.1"); // Ziel IP Adresse
    
    Datei.open("Verlauf_sender.txt", ios_base::out | ios::app);
    
    // Event erzeugen
    hEvent = CreateEvent( 
        0,         // default security attributes
        TRUE,         // manual-reset event
        0,         // initial state is non signaled
        0  // object name
        );
    
    nRet = connect(hSock,(SOCKADDR *)&receiver,sizeof(receiver));
    if(SOCKET_ERROR == nRet) cout << ::WSAGetLastError();
    cout << "connected" << endl;
    
    // Thread erzeugen
    //hThread = CreateThread( 
    //            NULL,              // default security attributes
    //            0,                 // use default stack size  
    //            ThreadProc,        // thread function 
    //            0,             // argument to thread function 
    //            0,                 // use default creation flags 
    //            &dwThreadId);   // returns the thread identifier
    
    while(true){
    	// Tesxtfarbe auf blau setzen
    	con.setTextColor(FG_BLUE);
    	// eine gnaze Zeile einlesen
    	getline(cin, buffer);
    	// Wenn exit eingegeben wird, beende die Eingabe und setze das Event
    	if(!strcmp(buffer.c_str(), "exit")){
    		SetEvent(hEvent);
    		buffer = "Partner hat den Chat verlassen";
    		Datei << buffer << endl;
    		while(!(nRet = send(hSock,&buffer[0],buffer.length(),0)));
    		break;
    	}
    	Datei << buffer << endl;
    	cout << "Daten senden" << endl;
    	// --- Daten senden -------------------
    	while(!(nRet = send(hSock,&buffer[0],buffer.length(),0)));
    }
    
    // --- Verbindung schliessen ----------
    nRet = shutdown(hSock,SD_BOTH);
    
    //DeleteCriticalSection(&CS);
    // --- Socket schliessen --------------
    nRet = closesocket(hSock);
    
    // --- Winsock deinitialisieren -------
    nRet = WSACleanup();
    
    // --- Winsock deinitialisieren -------
    nRet = WSACleanup();
    
    // Unendlich Warten bis der Thread ordnungsgemaes beendet wurde
    WaitForSingleObject(hThread, INFINITE);
    
    // Dateistream schließen
    Datei.close();
    
    return 0;
    }
    


  • Ceos schrieb:

    mal abgesehen davon, dein recv liefert entweder anzahl bytes oder 0 wenn verbindung getrennt oder -1 wenn fehler .... du solltest mal ne fehlerkontrolle einbauen und nicht einfach davon ausgehen das die verbindung schon irgendwie hinhaut.

    Hab jetzt sowas stehen

    nByte = recv(usocket,buffer,buffer_size,0);
    if(nByte < 0) cout << WSAGetLastError() ;
    

    Ich bekomme den Fehler 10093.
    Im help steht:

    Successful WSAStartup not yet performed.
    Either the application has not called WSAStartup or WSAStartup failed. The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks), or WSACleanup has been called too many times.

    Das scheint es zu sein was Probleme macht... und jetzt 😕



  • Du musst am Anfang deines Programms noch "WSAStartup()" aufrufen! Am Ende dann auch irgendwas zum aufräumen, bin mir aber nicht mehr sicher, evtl WSACleanUp, müsstest du aber auch bei der MSDN-Referenz zu WSAStartup finden 😉



  • Badestrand schrieb:

    Du musst am Anfang deines Programms noch "WSAStartup()" aufrufen! Am Ende dann auch irgendwas zum aufräumen, bin mir aber nicht mehr sicher, evtl WSACleanUp, müsstest du aber auch bei der MSDN-Referenz zu WSAStartup finden 😉

    Das hab ich aber in der main, das recv is ja oben drüber, vielleicht "findet" er deshalb das WSAStartup nicht.

    Wenn ich WSAStartup über den ThreadProc setze gibt er mir einen haufen Fehler, ich denke das muss in der main sein...



  • Oh, stimmt, entschuldige! Aber ich glaub ich habs: In deiner main rufst du WSACleanUp auf und dann wartest du auf die anderen Threads, heißt es wird aufgeräumt während die anderen Threads noch laufen. Mach das Cleanup einfach nach dem WaitForSingleObject.



  • Hey der Fehler ist weg, dafür hab ich jetzt folgenden bei recv:

    10038:
    Socket operation on nonsocket.
    An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.



  • Falls der gepostete Code noch aktuell ist, dann gehört shutdown () und closesocket () auch noch hinter WaitForSingleObject () und vor WSACleanup ().



  • Habs gelößt, war einiges falsch 🙄

    Danke an alle! 👍



  • werte den fehler bei deinem wsastartup doche einfach mal aus

    nRet = WSAStartup(wVersionRequested,&stWSAData);
    // Fehlerabfrage
    if(nRet < 0){
        cout << "Fehler bei WSAStartup";
        cout << WSAGetLastError(); //<----- so oder so ähnlich
    }
    

    EDIT: O_o ups da war ja noch ne seite 2 bei dem topic ... DAMN



  • MSDN:

    If successful, the WSAStartup function returns zero. Otherwise, it returns one of the error codes listed below.

    The WSAStartup function directly returns the extended error code in the return value for this function. A call to the WSAGetLastError function is not needed and should not be used.

    -> WSAGetLastError() sollte nicht benutzt werden bei WSAStartup(..).

    Simon



  • doppel autsch .... hast ja recht ... mittlerweilen kopier ich teile meines code nur noch, btw. hab mit ne tool lib angelegt und ruf einfach nur noch initWSA(); auf >_<


Anmelden zum Antworten