Socket Server / Client



  • Moin!

    In den Programmen soll man mit der Client Seite Nachrichten an die anderen Clienten schicken (Chatprogramm).

    Kann man den Clienten so verändern, dass die Eingabe für die zu schickene NAchricht parallel zum Empfang neuer Nachrichten ist? (Stichpunkt: C++ 11 / 14 Thread, etc?).

    Und wenn ja, gibt es in der Richtung keine Probleme mit dem Socket? (Verklemmung, etc)

    Danke

    Server:

    //#pragma comment( lib,"ws2_32.lib" )
    #include <windows.h>
    
    #include <winsock2.h> // bei manchan compilern muss man nur windows.h includieren (zB VC++)
    
    #include <stdio.h>
    
    #define MAX_CLIENTS 10
    
    int startWinsock(void) {
        WSADATA wsa;
        return WSAStartup(MAKEWORD(2,0),&wsa);
        }
    
    int main() {
        long rc;
        SOCKET acceptSocket;
        //SOCKET connectedSocket;
        SOCKADDR_IN addr;
        char buf[256];
        char buf2[300];
        // zusätzliche Variabeln
        FD_SET fdSet;
        SOCKET clients[MAX_CLIENTS];
        int i;
    
        // Winsock starten
        rc=startWinsock();
        if(rc!=0) {
            printf("Fehler: startWinsock, fehler code: %ld\n",rc);
            return 1;
        } else {
            printf("Winsock gestartet!\n");
        }
    
        // Socket erstellen
        acceptSocket=socket(AF_INET,SOCK_STREAM,0);
        if(acceptSocket==INVALID_SOCKET) {
            printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError());
            return 1;
        } else {
            printf("Socket erstellt!\n");
        }
    
        // Socket binden
        memset(&addr,0,sizeof(SOCKADDR_IN));
        addr.sin_family=AF_INET;
        addr.sin_port=htons(12345);
        addr.sin_addr.s_addr=INADDR_ANY; // gewisse compiler brauchen hier 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 12345 gebunden\n");
        }
    
        // In den listen Modus
        rc=listen(acceptSocket,10);
        if(rc==SOCKET_ERROR) {
            printf("Fehler: listen, fehler code: %d\n",WSAGetLastError());
            return 1;
        } else {
            printf("acceptSocket ist im listen Modus....\n");
        }
    
        for(i=0;i<MAX_CLIENTS;i++) {
            clients[i]=INVALID_SOCKET;
        }
    
        while(1) {
            FD_ZERO(&fdSet); // Inhalt leeren
            FD_SET(acceptSocket,&fdSet); // Den Socket der verbindungen annimmt hinzufügen
    
            // alle gültigen client sockets hinzufügen (nur die die nicht INVALID_SOCKET sind)
            for(i=0;i<MAX_CLIENTS;i++) {
                if(clients[i]!=INVALID_SOCKET) {
                    FD_SET(clients[i],&fdSet);
                }
            }
    
            rc=select(0,&fdSet,NULL,NULL,NULL);
            // nicht vergessen den ersten parameter bei anderen betriebssystem anzugeben
            if(rc==SOCKET_ERROR) {
                printf("Fehler: select, fehler code: %i\n",WSAGetLastError());
                return 1;
            }
    
            // acceptSocket is im fd_set? => verbindung annehmen (sofern es platz hat)
            if(FD_ISSET(acceptSocket,&fdSet)) {
                // einen freien platz für den neuen client suchen, und die verbingung annehmen
                for(i=0;i<MAX_CLIENTS;i++) {
                    if(clients[i]==INVALID_SOCKET) {
                        clients[i]=accept(acceptSocket,NULL,NULL);
                        printf("Neuen Client angenommen (%d)\n",i);
                        break;
                    }
                }
            }
            // prüfen wlecher client sockets im fd_set sind
            for(i=0;i<MAX_CLIENTS;i++) {
                if(clients[i]==INVALID_SOCKET) {
                    continue; // ungültiger socket, d.h. kein verbunder client an dieser position im array
                }
                if(FD_ISSET(clients[i],&fdSet)) {
                    rc=recv(clients[i],buf,256,0);
                    // prüfen ob die verbindung geschlossen wurde oder ein fehler auftrat
                    if(rc==0 || rc==SOCKET_ERROR) {
                        printf("Client %d hat die Verbindung geschlossen\n",i);
                        closesocket(clients[i]); // socket schliessen
                        clients[i]=INVALID_SOCKET; // seinen platz wieder freigeben
                    } else {
                        int j=0;
                        for(j=0;j<MAX_CLIENTS;j++) {
                            if (j==i) continue;  // aktueller client?
                                if(clients[j]==INVALID_SOCKET) {
                                    continue; // ungültiger socket, d.h. kein verbunder client an dieser position im array
                                }
                            send(clients[j],buf,(int)strlen(buf),0);
                        }
                        //buf[rc]='\0';
                        // daten ausgeben und eine antwort senden
                        //printf("Client %d hat folgendes gesandt: %s\n",i,buf);
                        // antwort senden
                        //sprintf(buf2,"Du mich auch %s\n",buf);
                        //send(clients[i],buf2,(int)strlen(buf2),0);
                    }
                }
            }
        }
    }
    

    Client:

    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    
    //Prototypen
    int startWinsock(void);
    long getAddrFromString(char* hostnameOrIp, SOCKADDR_IN* addr);
    
    int main(int argc, char** argv) {
        long rc;
        SOCKET s;
        SOCKADDR_IN addr;
        char buf[256];
    
        if(argc<2) {
            printf("Usage: sock <hostname oder ip des servers>\n");
            return 1;
        }
        // Winsock starten
        rc=startWinsock();
        if(rc!=0) {
            printf("Fehler: startWinsock, fehler code: %ld\n",rc);
            return 1;
        } else {
            printf("Winsock gestartet!\n");
        }
    
        // Socket erstellen
        s=socket(AF_INET,SOCK_STREAM,0);
        if(s==INVALID_SOCKET) {
            printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError());
            return 1;
        } else {
            printf("Socket erstellt!\n");
        }
    
        // Verbinden
        memset(&addr,0,sizeof(SOCKADDR_IN)); // zuerst alles auf 0 setzten
        addr.sin_family=AF_INET;
        addr.sin_port=htons(12345); // wir verwenden mal port 12345
        rc=getAddrFromString(argv[1],&addr);
        if(rc==SOCKET_ERROR) {
            printf("IP für %s konnte nicht aufgeloest werden\n", argv[1]);
            return 1;
        } else {
            printf("IP aufgeloest!\n");
        }
    
        rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR));
        if(rc==SOCKET_ERROR) {
            printf("Fehler: connect gescheitert, fehler code: %d\n",WSAGetLastError());
            return 1;
        } else {
            printf("Verbunden mit 127.0.0.1..\n");
        }
    
        // Daten austauschen
        while(rc!=SOCKET_ERROR) {
            printf("\nZeichenfolge eingeben [max 256]: ");
            gets(buf);
            send(s,buf,strlen(buf),0);
            rc=recv(s,buf,256,0);
            if(rc==0) {
                printf("Server hat die Verbindung getrennt..\n");
                break;
            }
            if(rc==SOCKET_ERROR) {
                printf("Fehler: recv, fehler code: %d\n",WSAGetLastError());
                break;
            }
            buf[rc]='\0';
            printf("\nServer antwortet: %s\n",buf);
        }
        closesocket(s);
        WSACleanup();
        return 0;
    }
    
    int startWinsock(void) {
        WSADATA wsa;
        return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    
    long getAddrFromString(char* hostnameOrIp, SOCKADDR_IN* addr) {
        //long rc;
        unsigned long ip;
        HOSTENT* he;
    
        /* Parameter prüfen */
        if(hostnameOrIp==NULL || addr==NULL) {
            return SOCKET_ERROR;
        }
        /* eine IP in hostnameOrIp ? */
        ip=inet_addr(hostnameOrIp);
    
        /* bei einem fehler liefert inet_addr den Rückgabewert INADDR_NONE */
        if(ip!=INADDR_NONE) {
            addr->sin_addr.s_addr=ip;
            return 0;
        } else {
            /* Hostname in hostnameOrIp auflösen */
            he=gethostbyname(hostnameOrIp);
            if(he==NULL) {
                return SOCKET_ERROR;
            } else {
                /*die 4 Bytes der IP von he nach addr kopieren */
                memcpy(&(addr->sin_addr),he->h_addr_list[0],4);
            }
            return 0;
    
        }
    }
    


  • Benutze C++ und (Boost.)Asio. Das ist einfacher.



  • TyRoXx schrieb:

    Benutze C++ und (Boost.)Asio. Das ist einfacher.

    Danke für diesen Hinweis.

    Wie muss ich dann bei Codeblocks 13.12 es einstellen bzw den Compiler konfigurieren, dass ich das in Boost kompilieren kann?

    Gibt es gute Tutorials für boost?

    Kann mir jemand bei meinem Problem für Winsock helfen?

    Danke






Anmelden zum Antworten