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 >_<