Chat Server und Client in C++



  • Hallo liebe Foren Mitglieder ich lese schon länger fleißig in diesem Forum mit und da ich nun auch mal einen Frage habe, habe ich mich gleich angemeldet um nachzufragen. Also ich bin noch Anfänger in C++ und weiß leider nicht was ich in meinem Programm falsch mache. Also ich hatte vor ein Chat Programm in C++ zu schreibe. Es sollen sich mehrere Cleinten mit dem Server verbinden können und die Narichten auch bei jedem Client ankommen. Doch das funktioniert leider nicht

    Server:

    #include <Winsock.h>
    #include <iostream>
    #include <windows.h>
    using namespace std;
    #pragma comment(lib, "ws2_32.lib")
    SOCKADDR_IN addr;           // Speichern von Port und IP
    int addrlen = sizeof(addr); // Länge des Ports und der IP
    int Counter;                // Zähler für verbundene Clients
    SOCKET sConnect;            // Einkommende Narichten
    SOCKET sListen;             // Ausgehende Narichten
    SOCKET* Connections;        // Verbundene Clients
    int InitWinSock()           // WinSock
    {
        int Val = 0;
        WSAData wsaData;
        WORD DLLVersion = MAKEWORD(2, 1);
        Val = WSAStartup(DLLVersion, &wsaData); // Einleitung von WinSock
        return Val;
    }
    int ServerThread(int ID) {
        char* Buffer = new char[256]; // Für jeden Client einen neuen Thread
        int size = 0;
        while (true) {
            ZeroMemory(Buffer, 256);
            if ((size = recv(Connections[ID], Buffer, 256, NULL)) > 0) // Wird nur getan wenn die Naricht nicht leer ist
                cout << Buffer << endl;
            {
                for (int a = 0; a > Counter; a++) // Das macht jeder Client im loop
                {
                    if (Connections[a] == Connections[ID]) {
                        ZeroMemory(Buffer, 256);
                        cout << ID << Buffer << endl;
                    } else // Die Naricht wird zu allen Client geschickt
                    {
                        ZeroMemory(Buffer, 256);
                        cout << ID << Buffer << endl;
                        send(Connections[a], Buffer, 256, NULL);
                        cout << Buffer << endl;
                    }
                }
            }
        }
    }
    int main() {
        system("color 0a"); // Konsolenfarbe Schwarz-Grün
        cout << "Server gestartet" << endl;
        int Val = InitWinSock();
        if (Val != 0) {
            MessageBoxA(NULL, "Fehler beim starten von WinSocket", "Fehler", MB_OK | MB_ICONERROR) exit(1);
        }
        Connections = (SOCKET*)calloc(64, sizeof(SOCKET));
        sListen = socket(AF_INET, SOCK_STREAM, NULL);
        sConnect = socket(AF_INET, SOCK_STREAM, NULL);
        addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Serveradresse in diesem Falle die lokale Adresse
        addr.sin_port = htons(2222);                   // Bereich in dem man Ports wählen darf
        addr.sin_family = AF_INET;                     // Art der Verbindung
        bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); // Verbinden des Servers mit unserer IP und unserem Port
        listen(sListen, 64);                           // Warten auf Anfragen von Clients
        while (true)                                   // Endless loop für Connections zu Clients
        {
            if (sConnect =
                  accept(sListen, (SOCKADDR*)&addr, &addrlen)) // Connection zu Client wurde gefunden und angenommen
            {
                Connections[Counter] = sConnect;
                char* Name = new char[64]; // Name des Clients
                ZeroMemory(Name, 64);      // Leeren des Chars
                sprintf(Name, "%i", Counter);
                send(Connections[Counter], Name, 64, NULL);
                send(Connections[Counter], "Willkommen auf dem Chat Server", 64, NULL);
                cout << "Neue Verbindung !" << endl;
                Counter++; // Ein Client mehr usw...
                CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ServerThread, (LPVOID)(Counter - 1), NULL, NULL);
            }
            Sleep(50);
        }
    }
    

    Client:

    #include <WinSock.h>
    #include <Windows.h>
    #include <iostream>
    using namespace std;
    #pragma comment(lib, "ws2_32.lib") // Libarie für WinSock
    SOCKET sConnect;                   // Einkommende Narichten
    SOCKADDR_IN addr;                  // Serveradresee
    int Startup_WinSock() {
        WSAData wsaData;
        WORD DLLVersion = MAKEWORD(2, 1);
        int Val = WSAStartup(DLLVersion, &wsaData);
        return Val;
    }
    int ClientThread() {
        char* Buffer = new char[256];
        int size = 0;
        cout << Buffer << endl;
        while (true) {
            ZeroMemory(Buffer, 256);
            if ((size = recv(sConnect, Buffer, 256, NULL)) > 0) {
                cout << Buffer << endl;
            }
            Sleep(50);
        }
    }
    int main() {
        system("color 0a");
        int Val = Startup_WinSock();
        if (Val != 0) {
            cout << "WinSock konnte nicht gestartet werden" << endl;
            exit(1);
        }
        sConnect = socket(AF_INET, SOCK_STREAM, NULL);
        addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Serveradresse in diesem Falle die lokale Adresse
        addr.sin_port = htons(2222);                   // Bereich in dem man Ports wählen darf
        addr.sin_family = AF_INET;                     // Art der Verbindung
        cout << "Bitte druecken sie die Enter Taste" << endl;
        cin.get();
        Val = connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));
        if (Val != 0) {
            cout << "Server kann nicht erreicht werden" << endl;
            main(); // Neuer Versuch
        } else {
            system("cls");
            int ID;
            char* nID = new char[64];   // deine ID
            char* Hallo = new char[64]; // Eine Naricht vom Server
            ZeroMemory(Hallo, 64);
            ZeroMemory(nID, 64);
            recv(sConnect, nID, 64, NULL);   // Empfang der Naricht
            recv(sConnect, Hallo, 64, NULL); // Empfang der Naricht
            ID = atoi(nID);
            cout << Hallo << endl;
            cout << "Deine ID ist:" << ID << endl;
            cout << "Wenn du bereit bist dann druecke bitte Enter erneut " << endl;
            cin.get();
            system("cls");
            cout << "Du > ";
            CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientThread, NULL, NULL, NULL); // CLient Thread
            while (true) {
                char* MSG = new char[256];
                ZeroMemory(MSG, 256);
                cin.getline(MSG, 256);
                send(sConnect, MSG, 256, NULL);
                Sleep(50);
            }
        }
        return 0;
    }
    

    Ich bedanke mich schonmal im vorraus für euere Antworten !!!

    Mod-Edit (camper): Code-Tags + clang-format



  • Hallo liebe Foren Mitglieder ich lese schon länger fleißig in diesem Forum mit

    Dann solltest du ja schon mitbekommen haben, dass

    Doch das funktioniert leider nicht

    keine ausreichende Fehlerbeschreibung ist.

    Codetags wären auch hilfreich.



  • Also wenn ich den Server starte und dann den Client dann verbindet sich der Client sofort mit dem Server. Das ist ja schonmal gut. Wenn ich im Client etwas schreibe wird das auch zum Server geschickt ABER der Server schickt die Naricht nicht an die anderen verbundenen Clienten weiter.



  • Entschuldigung habe vorhin vergessen den Code in Codetags zu schrieben

    Client:

    #include <WinSock.h>
    #include <iostream>
    #include <Windows.h>
    
    using namespace std;
    
    #pragma comment (lib, "ws2_32.lib") // Libarie für WinSock
    
    SOCKET sConnect; // Einkommende Narichten
    
    SOCKADDR_IN addr; //Serveradresee
    
    int Startup_WinSock ()
    {
    
    	WSAData wsaData;
    	WORD DLLVersion = MAKEWORD(2, 1);
    
    	int Val = WSAStartup (DLLVersion, &wsaData);
    
    	return Val;
    }
    
    int ClientThread()
    
    {
    	char *Buffer = new char[256];
    	int size = 0;
    	cout << Buffer << endl;
    
    	while (true)
    	{
    		ZeroMemory(Buffer, 256);
    
    		if ((size = recv(sConnect, Buffer, 256, NULL)) > 0)
    		{
    			cout << Buffer << endl;
    		}
    		Sleep(50);
    
    	}
    }
    
    int main ()
    
    {
    
    	system("color 0a");
    	int Val = Startup_WinSock();
    
    	if (Val != 0)
    	{
    		cout << "WinSock konnte nicht gestartet werden" << endl;
    		exit (1);
    	}
    
    	sConnect = socket(AF_INET, SOCK_STREAM, NULL);
    
    	addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Serveradresse in diesem Falle die lokale Adresse
    	addr.sin_port = htons(2222); // Bereich in dem man Ports wählen darf
    	addr.sin_family = AF_INET; //Art der Verbindung
    
    	cout << "Bitte druecken sie die Enter Taste" << endl;
    	cin.get();
    
    	Val = connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));
    
    	if (Val != 0)
    	{
    		cout << "Server kann nicht erreicht werden" << endl;
    		main(); //Neuer Versuch
    	}
    
    	else
    
    	{ 
    		system("cls");
    
    		int ID;
    		char *nID = new char[64]; //deine ID
    		char *Hallo = new char[64]; // Eine Naricht vom Server
    
    			ZeroMemory (Hallo, 64);
    		    ZeroMemory (nID, 64);
    
    			recv(sConnect, nID, 64, NULL);//Empfang der Naricht
    			recv(sConnect, Hallo, 64, NULL);//Empfang der Naricht
    
    			ID = atoi(nID);
    
    			cout << Hallo << endl;
    			cout << "Deine ID ist:" << ID << endl;
    			cout << "Wenn du bereit bist dann druecke bitte Enter erneut " << endl;
    			cin.get();
    
    			system("cls");
    
    			cout << "Du > ";
    
    			CreateThread (NULL, NULL, (LPTHREAD_START_ROUTINE) ClientThread, NULL, NULL, NULL);//CLient Thread
    
    			while (true)
    			{
    				char *MSG = new char[256];
    
    				ZeroMemory(MSG, 256);
    
    				cin.getline(MSG, 256);
    
    				send(sConnect, MSG, 256, NULL);
    
    				Sleep(50);
    			}
    
    	}
    
    	return 0;
    
    }
    

    Server:

    #include <Winsock.h> 
    #include <iostream>  
    #include <windows.h> 
    
    using namespace std;  
    
    #pragma comment (lib, "ws2_32.lib") 
    
    SOCKADDR_IN addr; // Speichern von Port und IP
    int addrlen = sizeof(addr); // Länge des Ports und der IP
    
    int Counter; //Zähler für verbundene Clients
    SOCKET sConnect; // Einkommende Narichten
    SOCKET sListen;  // Ausgehende Narichten
    SOCKET *Connections; //Verbundene Clients
    
    int InitWinSock()  // WinSock 
    {
    	int Val = 0; 
    	WSAData wsaData;
    	WORD DLLVersion = MAKEWORD (2, 1);
    
    	Val = WSAStartup(DLLVersion, &wsaData); // Einleitung von WinSock
    
    	return Val;
    }
    
    int ServerThread(int ID)
    {
    	char *Buffer = new char[256];// Für jeden Client einen neuen Thread 
    	int size = 0;
    
    while (true)
    
    {
    	ZeroMemory(Buffer, 256);
    
    	if ((size = recv(Connections[ID], Buffer, 256, NULL)) > 0)//Wird nur getan wenn die Naricht nicht leer ist
    		cout << Buffer << endl;
    	{
    		for (int a = 0; a > Counter; a++)// Das macht jeder Client im loop
    		{
    			if (Connections [a] == Connections[ID])
    		{
    				ZeroMemory(Buffer, 256);
    				cout << ID << Buffer << endl;
    
    			}
    
    			else//Die Naricht wird zu allen Client geschickt
    			{
    				ZeroMemory(Buffer, 256);
    				cout <<ID  << Buffer << endl;
    
    				send(Connections[a], Buffer, 256, NULL);
    				cout << Buffer << endl;
    
    			}
    		}
    	}
    }
    
    }
    
    int main()
    
    {
    	system("color 0a"); // Konsolenfarbe Schwarz-Grün
    	cout << "Server gestartet" << endl;
    	int Val = InitWinSock();
    
    	if (Val != 0)
    	{
    		MessageBoxA(NULL, "Fehler beim starten von WinSocket", "Fehler", MB_OK | MB_ICONERROR);
    		exit(1);
    	}
    
    	Connections = (SOCKET*) calloc (64, sizeof(SOCKET));
    
    	sListen = socket(AF_INET, SOCK_STREAM, NULL);
    	sConnect = socket(AF_INET, SOCK_STREAM, NULL);
    
    	addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Serveradresse in diesem Falle die lokale Adresse
    	addr.sin_port = htons(2222); // Bereich in dem man Ports wählen darf
    	addr.sin_family = AF_INET; //Art der Verbindung
    
    	bind (sListen, (SOCKADDR*)&addr, sizeof(addr)); //Verbinden des Servers mit unserer IP und unserem Port
    
    	listen(sListen, 64); //Warten auf Anfragen von Clients
    
    	while (true) //Endless loop für Connections zu Clients
    	{
    		if (sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen)) // Connection zu Client wurde gefunden und angenommen
    		{
    			Connections[Counter] = sConnect;
    			char *Name = new char[64];//Name des Clients
    
    			ZeroMemory(Name, 64);//Leeren des Chars
    
    			sprintf(Name, "%i", Counter);
    
    			send(Connections[Counter], Name, 64, NULL);
    			send(Connections[Counter], "Willkommen auf dem Chat Server", 64, NULL);
    
    			cout << "Neue Verbindung !" << endl;
    
    			Counter++; //Ein Client mehr usw...
    
    			CreateThread (NULL, NULL, (LPTHREAD_START_ROUTINE) ServerThread, (LPVOID)(Counter - 1), NULL, NULL);
    
    		}
    
    		Sleep(50);
    
    	}
    
    }
    


  • for (int a = 0; a > Counter; a++)
    

    Wie oft wird das ausgeführt?

    Benutze einen Debugger.

    Das

    char *Buffer = new char[256];
    

    sollte wohl besser

    char Buffer[256];
    // noch besser
    std::array<char,256> Buffer;
    

    sein.
    256 könnte man auch als const int verwenden.



  • Also ich habe mir gedacht das jeder Client eine Nummer zugewiesen bekommt und die dann immer vor seinem Text erscheint. also z.b. Client und dann die Variablenen (z.b. Client 1: Hallo, Client 2: Wie gehts) Der Chat soll eh annonym sein von daher nur Zahlen als Namen.

    for (int a = 0; a > Counter; a++)
    


  • Also ich habe mir gedacht das jeder Client eine Nummer zugewiesen bekommt und die dann immer vor seinem Text erscheint. also z.b. Client und dann die Variablenen (z.b. Client 1: Hallo, Client 2: Wie gehts) Der Chat soll eh annonym sein von daher nur Zahlen als Namen.

    for (int a = 0; a > Counter; a++)
    


  • Programmer2000 schrieb:

    Also ich habe mir gedacht das jeder Client eine Nummer zugewiesen bekommt und die dann immer vor seinem Text erscheint. also z.b. Client und dann die Variablenen (z.b. Client 1: Hallo, Client 2: Wie gehts) Der Chat soll eh annonym sein von daher nur Zahlen als Namen.

    for (int a = 0; a > Counter; a++)
    

    Und wie ist die Antwort auf meine Frage?



  • Ja es wird so oft ausgeführt wie Clienten den Server betreten.



  • Programmer2000 schrieb:

    Ja es wird so oft ausgeführt wie Clienten den Server betreten.

    Ich glaube nicht. Das soll es wohl tun, macht aber etwas anderes. Welchen Wert hat a ? Welchen Wert hat Counter ?



  • Also a fängt mit dem Wert 0 an und erhöht sich durch jeden Client der beitritt um 1. Das klappt auch soweit.



  • Programmer2000 schrieb:

    Also a fängt mit dem Wert 0 an und erhöht sich durch jeden Client der beitritt um 1. Das klappt auch soweit.

    Nein!



  • ok dann erkläre es mir bitte. Wie gesagt ich bin noch Anfänger



  • for (int a = 0; a > Counter; a++)
    vs.
    for (int a = 0; a < Counter; a++)



  • Danke



  • Es funktioniert leider immer noch nicht so wie ich es mir erhofft habe. Irgendwie leitet der Server den Text des einen Clienten nicht zu dem anderen Clienten weiter;(



  • Vielleicht ist ZeroMemory vor dem Senden ungeschickt.



  • OH SCHEISSE



  • Also irgendwie steh ich gerade auf dem Schlauch. Ich bekomm es immer noch nicht hin. Aber danke manni66 habe das ZeroMemory entfernt



  • Ich habe jetzt ZeroMemory entfernt. Wenn ich jetzt von einem Client zum anderen eine Naricht sende funktioniert dies auch !!;);) ABER wenn ich von dem Client der die Naricht erhalten hat eine Naricht zurückschreibe kommt auf dem anderen Client keine Antwort an.


Log in to reply