Server-Client-connection Sockets



  • Hallo,
    ich habe gerade ein server- und ein client-programm geschrieben (mit Hilfe des folgenden tutorials: http://www.c-worker.ch/tuts/wstut_op.php ).

    client und server geben folgendes aus:

    Server schrieb:

    Winsock gestartet!
    Socket erstellt!
    Socket an port 12345 gebunden
    acceptSocket wartet auf Verbindungen.....

    Client schrieb:

    Winsock gestartet!
    Socket erstellt!

    das heißt es ist alles bis zum verbindungsaufbau ok. allerdings wird keine verbindung aufgebaut 😞 und seltsamerweise erhalte ich weder die definierte fehlermeldung mit dem zugehörigen fehlercode noch die nachricht dass die verbinding aufgebut wurde.

    wenn eine verbindung aufgebaut wurde sollte ja laut code das hier ausgegeben werden:

    Server schrieb:

    Neue Verbindung wurde akzeptiert!

    Client schrieb:

    Verbunden mit [IP]

    was mache ich denn falsch? normal sollte doch wenigstens die fehlermeldung ausgegeben werden?! 😕

    hier mein code:

    server:

    #include <winsock2.h>
    #include <windows.h>
    #include <stdio.h>//Prototypen
    #include<conio.h>
    
    #pragma comment( lib, "ws2_32.lib" )
    int startWinsock(void);int main()
    
    {
      long rc;
      SOCKET acceptSocket;
      SOCKADDR_IN addr;  // Winsock starten
      rc=startWinsock();
    
      if(rc!=0)
      {
        printf("Fehler: startWinsock, fehler code: %d\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());
      }
    
      else
      {
        printf("Socket erstellt!\n");
      } 
      //binden des sockets an einen port:
      memset(&addr,0,sizeof(SOCKADDR_IN));
    
    addr.sin_family=AF_INET;
    addr.sin_port=htons(12345);
    addr.sin_addr.s_addr=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");
    }
    
      //auf verbindingen warten:
      rc=listen(acceptSocket,100);
    
    if(rc==SOCKET_ERROR)
    {
      printf("Fehler: listen, fehler code: %d\n",WSAGetLastError());
      return 1;
    }
    
    else
    {
      printf("acceptSocket ist im listen Modus....\n"); 
    }
    //Verbindingen annehmen:
    SOCKET connectedSocket;
    
    connectedSocket=accept(acceptSocket,NULL,NULL);
    
    if(connectedSocket==INVALID_SOCKET)
    
    {
      printf("Fehler: accept, fehler code: %d\n",WSAGetLastError());
      return 1;
    }
    
    else
    
    {
      printf("Neue Verbindung wurde akzeptiert!\n");
    }
    
    //bricht aber bei verbinding noch ab weil dann programm zu ende!
    
    getch();
    
    }
    
    int startWinsock(void)
    {
      WSADATA wsa;
      return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    

    Client:

    #include<winsock2.h>//IMMER VOR WINDOWS.H INCLUDEN!!!
    #include <windows.h>
    #include <stdio.h>
    #include<iostream>
    #include<conio.h>
    using namespace std;
    
    #pragma comment( lib, "ws2_32.lib" )
    
    int startWinsock(void);
    sockaddr_in addr;//fehlt im tutorial!!!
    
    int main()
    {	
    //Initialisierungen
      long rc=startWinsock();//sockets initialisieren
      SOCKET s;
    
      //abfrage ob initialisierung erfolgreich
      if(rc!=0)
      {
        printf("Fehler: startWinsock, fehler code: %d\n",rc);
        return 1;
      }
    
      else
      {
        printf("Winsock gestartet!\n");
      }
      //Socket erstellen
      s=socket(AF_INET,SOCK_STREAM,0);
    
      //Erstellen überprüfen durch return value socket(...)!=INVALID_SOcKET
    
    if(s==INVALID_SOCKET)
    {
      printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError());
      return 1;
    }
    
    else
    {
      printf("Socket erstellt!\n");
    }
    
    //Verbindung mit server herstellen
    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
    addr.sin_addr.s_addr=inet_addr("217.229.18.212"); // zielrechner ist unser eigener
    
    rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR));
    
    if(rc==SOCKET_ERROR)
    {
      printf("Fehler: connect gescheitert, fehler code: %d\n",WSAGetLastError());
    }
    
    else
    {
      printf("Verbunden mit 217.229.18.212\n");
    }
    
    //zeit zum klesen der konsolenausgaben lassen nd auf tastendruck warten
      getch();
      return 0;
    }
    
    int startWinsock(void)
    {
      WSADATA wsa;
      return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    

    woran liegt das denn? was mache ich falsch???

    danke schonmal für die hilfe,
    andi01.



  • Ich habe Deinen Client - Code unverändert genommen und er funktioniert wie gewünscht. D.h., er gibt aus:

    Winsock gestartet!
    Socket erstellt!
    Fehler: connect gescheitert, fehler code: 10054

    Es dauert allerdings eine Weile, bis der connect - Versuch aufgegeben wird, also Geduld!
    Den eigenen Rechner erreichst Du übrigens unter der IP 127.0.0.1



  • Es dauert allerdings eine Weile, bis der connect - Versuch aufgegeben wird, also Geduld!

    wow, danke! er funktioniert!!! ich wusste nicht dass ich etwas warten muss^^ 😃 ty 🙂

    Den eigenen Rechner erreichst Du übrigens unter der IP 127.0.0.1

    achsooo, ich hab die ip von www.wieistmeineip.de genommen 😃

    danke, jetzt geht's!

    jetzt muss ich nur noch das senden und empfangen von Daten hinkriegen, aber das mache ich morgen 😃

    danke schonmal für deine hilfe, die hat mich ein ganzes stück weitergebracht! 🙂

    mfg,
    andi01.



  • andi01 schrieb:

    Den eigenen Rechner erreichst Du übrigens unter der IP 127.0.0.1

    achsooo, ich hab die ip von www.wieistmeineip.de genommen 😃

    mfg,
    andi01.

    du localhost hacker du.



  • andi01 schrieb:

    achsooo, ich hab die ip von www.wieistmeineip.de genommen 😃

    Das ist die Adresse, unter der Du von außen erreichbar bist. Falls Du keinen Router benutzt, sollte das auch problemlos funktionieren, wenn Dein PC hinter einem Router hängt, musst Du den Router so konfigurieren, daß Anfragen auf dem gewünschten Port an Deinen Rechner weitergeleitet werden.



  • jetzt muss ich nur noch die datenübertragung hinkriegen^^

    mal sehen wie weit ich damit selbst komme. das ganze soll nämlich eine art ping werden. server und client können aber schon beide senden und empfangen, oder?

    mfg,
    andi01.



  • ok, senden und empfangen klappt. nur die frage ist wie schaffe ich es dass der user die ip eingeben kann wo der server ist? bei meinen versuchen kamen leider fehlermeldungen. ist ja aber nicht viel code. hat jemand vllt mal ein kleines bsp?

    danke schonmal,
    andi01.



  • ok, das mit dem bsp hat sich erledigt, habs hingekriegt. nur noch eine kleine frage: wie erreiche ich einen anderen pc der hinter demselben rooter hängt? 128.0.0.1? mein pc ist ja 127.0.0.1

    danke schonmal,
    andi01.



  • andi01 schrieb:

    ok, das mit dem bsp hat sich erledigt, habs hingekriegt. nur noch eine kleine frage: wie erreiche ich einen anderen pc der hinter demselben rooter hängt? 128.0.0.1? mein pc ist ja 127.0.0.1

    danke schonmal,
    andi01.

    Mit ipconfig am anderen PC kannst du die Addresse sehen.



  • danke. jetzt klappts, juhu!!! 🙂

    nur noch ein paar kleine fragen:

    1.: als rooter ist ne fritzbox vorgeschaltet. wie komme ich jetzt von außen an den pc ran? über die normale ip, oder?

    2.: grundsätzlich ist es egal welchen (geöffneten) port ich verwende, oder gibt es da wsntliche unterschiede?

    3.: da ist doch noch eine wesentlich frage aufgetaucht: wenn ich messages mit leerzeichen schicke werden die aufgetielt, in einer message ist immer der inghalt bis zum nächsten leerzeichen!? kann ich dass irgendwie verhindern?

    4.: üblicherweise kompilere ich das projekt fehlerfrei mit MS Visual C++ 2008 Express Editon, wenn ich es aber mit Dev C++ (ja, ich wiß der is veraltet usw 😃 ) kompilere kommen lauter fehlermeldungen mit undefined reference to ..., muss ich da noch irgendwas includen?

    danke schonmal,
    andi01.



    jain, du musst erst "ports forwarden", d.h. in dem router einstellen,
    welche ports er von "draußen" an welchen pc innen durchlassen soll.
    im hauptmenü sollte das einstellbar sein (im webbrowser 192.168.2.1 eingeben als URL)

    2.)
    du hast die komplette reichweite eines short zur verfügung (0 - ~65365),
    aber ports < 1024 können nur vom admin genutzt werden. ich vermeide diese generell.

    natürlich wäre es sehr ungünstig wenn zwei programme über den selben port kommunizieren. allerdings solltest du zwischen 1025 und 65000 etwas freies finden.

    wenn möglich sollte aber der benutzer selber wählen, welchen port er nimmt.
    bei internet-anwendungen geht das sehr selten, aber du kannst ja "einfach"
    mehrere ports erlauben. oder halt hoffen einen freien zu erwischen 😉

    3.)

    wie sendest und empfängst du? normalerweise sendet man binär, da kannn
    eine leertaste und auch ein '\0'-terminator kommen wie er lustig ist.

    ich lege mir z.b. einen "kleinen" puffer irgentwo einmal an, z.b. 64kb und
    gebe den an z.b. recv (wenn du TCP nimmst). recv gibt mir im erfolgsfall die
    anzahl der gelesenen bytes zurück. damit kannst du dir ja den rest zusammenbauen.

    die sender-seite kann einfach den string in den socket stopfen, hier muss man
    nicht viel beachten.

    achja. der nullterminator wird meist nicht mitgesendet. entweder du sendest
    length + 1, oder du terminierst dir das ganze selber, wieviel empfangen
    wurde weißt du ja.

    4.)

    V E R A L T E T !
    nicht nehmen! böse! wenn du kein msvc nimmst, wegen diversen sachen, kannst du
    code::blocks nehmen + mingw, das hat sich sehr bewährt bei mir.

    versuch mal die "Ws2_32.lib" zu linken.



  • wie sendest und empfängst du?

    der code gabz oben von s.1 ist nich immer unverändert, das sind die kompletten codes für client und server.

    V E R A L T E T !
    nicht nehmen! böse! wenn du kein msvc nimmst, wegen diversen sachen, kannst du
    code::blocks nehmen + mingw, das hat sich sehr bewährt bei mir.

    ja, ich weiß! nur leider kann ich MS Visual C++ 2008 Express Edition nicht verwenden 😞 😞 , denn wenn ich es damit kompilere und auf einem pc ausführe wo diese entwicklungsumgebung nicht nstalliert ist kommt folgende fehlermeldung:

    Fehlermeldung schrieb:

    Diese Anwendung konnte nicht gestartet werden, weil die Anwendungskonfiguration nicht korrekt ist. zur problembehebung sollten Sie die anwendung neu installieren.

    ich habe bereits alles versucht um das wegzukriegen, aber keine chance. egal was ich gemacht habe es kam immer dieser fehler. nach ein paar wochen intensiven erfolglosen lösungsversuchen hab ichs aufgegeben und benutze deshalb von nun an für anwendungen die auch auf anderen pcs laufen sollen dev c++, da kommt die meldung nicht und alles geht. 🙂

    ich bin mit dieser lösung selbst auch nicht glücklich, es ist eine notlösung. nur leider kann ich diesen fehler einfach nicht beheben. wenn jemand weiß wie man das macht würde ich sehr gerne wieder MS Visual C++ 2008 E E verwenden 😃

    wie kann ich dieses problem denn beseitigen?

    danke schonmal,
    andi01.



  • andi01 schrieb:

    ich habe bereits alles versucht um das wegzukriegen, aber keine chance. egal was ich gemacht habe es kam immer dieser fehler. nach ein paar wochen intensiven erfolglosen lösungsversuchen hab ichs aufgegeben

    hehe 😃 🙂

    projekt -> eigenschaften -> konfiguration -> C/C++ -> codegeneration ->
    laufzeitbibliothek -> "multithreaded" ohne DLL!

    und siehe da

    🙂



  • dann kommen aber fehlermeldungen beim kompilern 😮
    muss ich da dann noch was includen?

    überhaupt verstehe ich die frage

    wie sendest du?

    nicht. ich sende halt einfach mit dem befhel send() im obigen clientcode.

    mfg,
    andi01.



  • andi01 schrieb:

    dann kommen aber fehlermeldungen beim kompilern 😮
    andi01.

    welche?

    du kannst entweder deine strings bis zum 0-terminator senden:

    send(soc, str.c_str(), str.length(), 0);
    

    oder mit dem terminator:

    send(soc, str.c_str(), str.length() + 1, 0);
    

    vorteil: einfacheres empfangen.
    nachteil: ein byte mehr *ironie off*

    oder du schreibst dir ein protokoll:

    struct data
    {
        unsigned type;
        unsigned size;
    };
    
    data *ptr = malloc(sizeof(data) + str.length());
    ptr->type = string_type; // ein enum
    ptr->size = sizeof(data) + str.length();
    memcpy(ptr + 1, str.c_str(), str.length());
    
    send(soc, data, data->size, 0);
    

    letzteres ist am flexibelsten, aber nicht ganz einfach 😉



  • und free nicht vergessen...



  • sollte normal sein alles wieder freizugeben (hoffe ich mal) 😉
    viele vergessen das immer, dabei ist das doch ganz einfach.


Anmelden zum Antworten