Nachrichten empfangen solange Enter nicht gedrückt



  • Hallo zusammen,

    ich habe einen Chat mit Client und Server geschrieben. Server klappt so wie es soll, leider komme ich bei dem Client nicht so ganz weiter.

    Ich möchte, dass der Client Nachrichten empfangen kann solange nicht Enter gedrückt wurde, damit der User selber nachrichten eintippen kann.

    Auszug:

    // Soll immer wieder ausgeführt werden
    while (1)
    	{
    //Solange Enter nicht gedrückt wird soll es nachrichten empfangen
    	while (getchar() != 0x0A) {
    			memset(&recvbuf, 0, sizeof(recvbuf));
    			rc = recv(sConnect, recvbuf, 256, 0);
    			if (rc == SOCKET_ERROR)
    				cout << "error recv(): " << WSAGetLastError() << endl;
    			else
    			{
    				cout << rc << " bytes erhalten: "
    					<< recvbuf << endl;
    
    			}
    		}
    // Wenn Enter gedrückt wurde geht es aus der Schleife und Senden
    // soll möglich sein
    		memset(&sendbuf, 0, sizeof(sendbuf));
    		cout << "Nachricht: ";
    		cin.getline(sendbuf, 256);
    
    		rc = send(sConnect, sendbuf, strlen(sendbuf), 0);
    		if (rc == SOCKET_ERROR)
    			cout << "error send(): " << WSAGetLastError() << endl;
    		else
    			cout << rc << " bytes gesendet" << endl;	
    	}
    

    Gibt es andere Möglichkeiten? Kann man auch irgendwie Senden und empfangen gleichzeitig lösen? Also auch wenn man schreibt sollen nachrichten empfangen werden.

    Vielen Dank!



  • Schau dir mal die Funktion select() an. Z.B.: http://www.zotteljedi.de/socket-tipps/select.html

    Da kann man auch ein Timeout angeben.
    Um zu sehen, ob Zeichen an stdin (oder Tastatur) anliegen, brauchst du aber Systemabhängige Funktionen.

    PS. Diese Informationen gelten für C, da du hier im C-Unterforum bist.
    Für C++ mag das (gerade mit BOOST) anders aussehen.



  • DirkB schrieb:

    Schau dir mal die Funktion select() an. Z.B.: http://www.zotteljedi.de/socket-tipps/select.html

    Da kann man auch ein Timeout angeben.
    Um zu sehen, ob Zeichen an stdin (oder Tastatur) anliegen, brauchst du aber Systemabhängige Funktionen.

    PS. Diese Informationen gelten für C, da du hier im C-Unterforum bist.
    Für C++ mag das (gerade mit BOOST) anders aussehen.

    Select habe ich für den Server angewendet, damit mehrere Clients gleichzeitig behandelt werden können. Ich blicke nicht durch, wie ich das vorteilhaft hier einbauen kann.



  • Thisisit schrieb:

    Select habe ich für den Server angewendet, damit mehrere Clients gleichzeitig behandelt werden können. Ich blicke nicht durch, wie ich das vorteilhaft hier einbauen kann.

    Hast du dir den Link mal angesehen?

    Zotteljedi schrieb:

    select() kann übrigens nicht nur verwendet werden, um herauszufinden ob von einem Socket gelesen werden kann ohne zu blockieren.

    Zotteljedi schrieb:

    select() arbeitet übrigens, wie viele der anderen "Socket"-Funktionen auch, ebenfalls auf Deskriptoren wie sie von pipe() oder open() geliefert werden. Damit ist es z.B. sehr simpel einen Konsolen-Client zu schreiben, der auf die Tastatur und auf eine Netzwerkverbindung achten muß.

    Schau halt mal auf der Seite http://www.zotteljedi.de/ unter Schriften zur Programmierung bei den sockets nach

    Wie aber schon gesagt, ist das vor allem C.

    Du programmierst aber C++



  • Nutze ich Select so richtig? Wie kann ich jetzt sagen, wenn etwas zu lesen gibt soll die Funktion aktiv werden sonst soll es bei Send bleiben?

    fd_set Socketlist;
    	FD_ZERO(&Socketlist);
    	FD_SET(sConnect, &Socketlist);
    
    	while (1)
    	{
    		fd_set SocketlistCopy = Socketlist;
    
    		int socketAnzahl = select(0, &SocketlistCopy, nullptr, nullptr, nullptr);
    		char buf[4096];
    		ZeroMemory(buf, 4096);
    
    		int bytesIn = recv(sConnect, buf, 4096, 0);
    		cout <<  bytesIn << " bytes erhalten: " << buf << endl;
    
    		memset(&sendbuf, 0, sizeof(sendbuf));
    		cout << "Nachricht: ";
    		cin.getline(sendbuf, 256);
    
    		rc = send(sConnect, sendbuf, strlen(sendbuf), 0);
    		if (rc == SOCKET_ERROR)
    			cout << "error send(): " << WSAGetLastError() << endl;
    		else
    			cout << rc << " bytes gesendet" << endl;	
    	}
    


  • Thisisit schrieb:

    Nutze ich Select so richtig?

    Der erste Paramter gibt an, auf wieviel Deskriptoren maximal (max+1) geachtet werden soll.
    Bei dir ist der dummerweise 0.

    STDIN darf da auch drin sein.

    select wartet jetzt so lange, bis einer der überwachten Deskriptoren ein Ereignis hat.
    Dies kannst du überprüfen, in dem du die übergebenen fd_set auswertest.
    Du hast nur den für read .

    Wenn da was zu lesen ist, dann lies.

    Aber du benutzt das ja schon im Server.



  • Für Windows steht in meiner Quelle, dass eine Eingabe nicht nötig sei für die erste Stelle bei select. Bytes senden funktioniert soweit bis auf Empfangen. Ich erkenne mein Fehler nicht

    while (1) {
    
    		while (getchar() == 0x0A) {
    			memset(&sendbuf, 0, sizeof(sendbuf));
    			cout << "Nachricht: ";
    			cin.getline(sendbuf, 256);
    
    			rc = send(sConnect, sendbuf, strlen(sendbuf), 0);
    			if (rc == SOCKET_ERROR)
    				cout << "error send(): " << WSAGetLastError() << endl;
    			else
    				cout << rc << " bytes gesendet" << endl;
    
    		}
    		FD_ZERO(&fdSetRead);
    		FD_SET(sConnect, &fdSetRead);
    		timeout.tv_sec = 0;
    		timeout.tv_usec = 0;
    
    		while ((rc = select(0, &fdSetRead, NULL, NULL, &timeout))>0) {
    			memset(&recvbuf, 0, sizeof(recvbuf));
    			rc = recv(sConnect, recvbuf, 256, 0);
    			if (rc == SOCKET_ERROR)
    				cout << "error recv(): " << WSAGetLastError() << endl;
    			else
    			{
    				cout << rc << " bytes erhalten: "
    					<< recvbuf << endl;
    			}
    			}
    


  • Ist stdin bei dir blockierend?



  • DirkB schrieb:

    Ist stdin bei dir blockierend?

    An welcher stelle meinst du das?

    Edit: Ich merke das ich erst Nachrichten empfange wenn ich in der Console etwas schreibe und Enter drücke. Woran kann das liegen?
    Also ich schreibe etwas drücke Enter und bei dem anderen Client muss ich etwas eintippen und enter drücken dann erst wird die nachricht angezeigt.



  • Thisisit schrieb:

    Edit: Ich merke das ich erst Nachrichten empfange wenn ich in der Console etwas schreibe und Enter drücke. Woran kann das liegen?

    Daran, dass stdin blockierend ist.
    getline wartet solange, bis eine Zeile (mit Enter) eingegeben wurde.

    Allerdings gibt stdin (meistens) auch erst die Daten weiter, wenn Enter gedrückt wurde.

    Darum auch der (mehrmalige) Hinweis, dass select auch mit STDIN klar kommt.



  • Wie kann ich den Stdin bei select definieren, das habe ich nicht ganz verstanden?



  • Thisisit schrieb:

    Wie kann ich den Stdin bei select definieren, das habe ich nicht ganz verstanden?

    Du hast auch nicht verstanden, daß Du im falschen Forum postest 🤡



  • ralros schrieb:

    Thisisit schrieb:

    Wie kann ich den Stdin bei select definieren, das habe ich nicht ganz verstanden?

    Du hast auch nicht verstanden, daß Du im falschen Forum postest 🤡

    Kann jemand den Thread verschieben oder soll ich eine neue erstellen. Ich bin kurz vor dem Ziel 🙄



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (alle ISO-Standards) in das Forum C++ (alle ISO-Standards) verschoben.

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

    Dieses Posting wurde automatisch erzeugt.



  • Hat sich geklärt getchar war das problem. Danke


Log in to reply