Server soll befehle ausführen



  • Hey folgendes ich hab mir einen client und einen server gebastelt mit dem code aus nem tut und nun hab ich zwei probleme 1. wie krieg ich hin das man beim client die ip des servers angibt und 2. soll zb wenn ich eine 1 sende der server den befehl unter 1 bei einem switch ausführen... beides funzt aber net

    hier mal der client

    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    
    //Prototypen
    int startWinsock(void);
    char serverip[20];
    
    int main()
    {
      long rc;
      SOCKET s;
      SOCKADDR_IN addr;
      char buf[256];
      char ip;
    
      printf("Bitte Ziel-IP eingeben: ");
       scanf("%c",&ip);
       fflush(stdin);
    
      // Winsock starten
      rc=startWinsock();
      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);
      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
      addr.sin_addr.s_addr=inet_addr("127.0.0.1"); 
    
     /* Was muss ich nun anstatt "127.0.0.1" eingeben.. hab ja schon ne abfrage der ip am anfang mit char*/
    
      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 %c \n",ip);
      }
    
      // Daten austauschen
      while(rc!=SOCKET_ERROR)
      {
        printf("\nBitte Befehl eingeben: ");
        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);
    }
    

    und hier mal der server

    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    
    //Prototypen
    int startWinsock(void);
    
    int main()
    {
      long rc;
      SOCKET acceptSocket;
      SOCKET connectedSocket;
      SOCKADDR_IN addr;
      char buf[256];
      char buf2[300];
    
      // 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());
        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=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");
      }
    
      // Verbindung annehmen
      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");
      }
    
      // Daten austauschen
      while(rc!=SOCKET_ERROR)
      {
        rc=recv(connectedSocket,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("Client sendet: %s\n",buf);
    
          switch(buf) {
    
          case 8 :  printf("\n PC wird heruntergefahren \n\n");
                    system("C:\\WINDOWS\\System32\\shutdown.exe -s -f -t 0 ");  
                    break;                                 
    
          case 9 :  printf("\n Programm wird beendet \n");      break;
    
          default:  printf("\n Unbekannte Auswahl \n\n");
          }
        sprintf(buf2,"Du mich auch %s",buf);
        rc=send(connectedSocket,buf2,strlen(buf2),0);
      }
      closesocket(acceptSocket);
      closesocket(connectedSocket);
      WSACleanup();
      return 0;
    }
    
    int startWinsock(void)
    {
      WSADATA wsa;
      return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    

    Ich benutz win xp und borland compiler... und beim kompilieren vom server krieg cih den fehler das ich integer beim switch brauch.. und wenn ich zb case 'asd' nehme um auf char zuzugreifen gibts noch mehr fehler...

    ich denk mir die variable buf passt halt net aber wie und vorallem kann ich die passen umformatieren

    ich hoffe ma ihr könnt mir helfen weil ich hab echt keinen plan was ich noch mahcen soll... hab schon seit stunden daran rumgebastelt aber noch will funzen



  • Mit switch kannst du nur Integer-Werte vergleichen. Wenn du einzelne Zeichen (z. B. das erste Zeichen in deiner Zeichenkette), kannst du switch (buf [0]) verwenden. Außerdem vergleichst du mit Zahlen: '8' ist nicht das selbe wie 8 .

    Wenn du ganze Zeichenketten vergleichen willst:

    if (!strcmp (buf, "8"))
    {
        ...
    }
    else if (!strcmp (buf, "9"))
    {
        ...
    }
    ...
    


  • devkid schrieb:

    Mit switch kannst du nur Integer-Werte vergleichen. Wenn du einzelne Zeichen (z. B. das erste Zeichen in deiner Zeichenkette), kannst du switch (buf [0]) verwenden. Außerdem vergleichst du mit Zahlen: '8' ist nicht das selbe wie 8 .

    Wenn du ganze Zeichenketten vergleichen willst:

    if (!strcmp (buf, "8"))
    {
        ...
    }
    else if (!strcmp (buf, "9"))
    {
        ...
    }
    ...
    

    recv(..) empfängt nicht zwingend den ganzen String auf einmal. Dh. ev. ist der "String" nocht nicht null terminiert. Das würde strcmp(..) ganz schön durcheinander bringen.

    Simon



  • hallo und ojemine

    gleich am anfang des clients musst du ein array statt eines einzelnen zeichens deklarieren und zwar soviel um eine ip in dotted-schreibweise zu fassen. z.b.:

    char ip[64]; // sollte reichen
    scanf("%s", ip); // string einlesen
    

    bei der printf-aktion gilt das selbe.

    dann

    fflush(stdin);
    

    ist verboten! wo haben die leute das immer her 🙄

    die ip gibst du einfach mit

    inet_addr(ip);
    

    an

    da du nur eine ziffer sendest, kannst du auch direkt mit

    buffer[0] == '1'
    

    arbeiten. ich würde allerdings auf der client-seite den befehl in ein z.b. int
    umwandeln und den dann senden. desweiteren ist es nicht garantiert,
    dass send alles mitnimmt was man reinstopft und recv auch nicht alles ausgibt.

    es kann durchaus sein, dass die hälfte noch unterwegs ist. du musst also in einer schleife solange senden bis alles weg ist und auch in einer schleife alles wieder empfangen, bis du das volle packet hast. dazu könnte man einfach die größe vorne weg schicken:

    // SENDEN
    unsigned size = strlen(buf);
    int result = send(soc, reinterpret_cast<char *>(&size), sizeof(size), 0);
    // result testen
    unsigned rest = size;
    while (rest)
    {
        result = send(soc, reinterpret_cast<char *>(buf) + (size - rest), rest, 0);
        if (result == 0)
            // verbindung getrennt
        if (result == -1)
            // error
        rest -= result;
    }
    // EMPFANGEN:
    unsigned size;
    inr result = recv(soc, reinterpret_cast<char *>(&size), sizeof(size), 0);
    // result testen
    char *buf = new char[size]; // löschen nicht vergessen!!
    unsigned rest = size;
    while (rest)
    {
        result = recv(reinterpret_cast<char *>(buf) + (size - rest), rest, 0);
        if (result == 0)
            // verbindung getrennt
        if (result == -1)
            // error
        rest -= result;
    }
    

    allerding ist es unwahrscheinlich, dass das netzwerk ein 2 Byte Packet zerlegt.
    desweiteren sendet windows immer alles oder nichts, weshalb man sich die schleife sparen kann. ist jedoch sonst nicht portabel :p

    btw: falsches forum 🙂



  • ok danke für die antowrten und den support soweit... ich werd des morgen mal soweit probiern umzusetzen

    der string wir doch hiermit null-terminiert oder hab ich da was falsch verstanden

    buf[rc]='\0';
        printf("Client sendet: %s\n",buf);
    

    ach und

    fflush(stdin);
    

    hab ich aus em c/c++ tutorial von galileo computing oder so

    und wie kann ich mit

    send(s,buf,strlen(buf),0);
    

    einen int wert senden
    buf muss doch char sein

    sry für die noob fragen aber ich hab halt schon lang nixmehr mit c/c++ gemacht und war eh nie viel weiter wwie die basics, die ich halt noch halbwegs so drauf hab 😉



  • buf muss doch char sein

    Nein, buf muss const char* sein (dein array wird in einen solchen pointer "konvertiert".). Du kannst auf alles sinnige und unsinnige mit buf als const char* zeigen und damit versenden.

    Edit:
    Bsp:
    const char* buf = reinterpret_cast<const char*>(&a);
    const size_t len = sizeof(a);
    int ret = send(s, buf, len, 0);

    Simon



  • ich hab jetz ma alles soweit umgesetzt und jetzt funktioniert es endlich nochmals vielen dank an euch



  • so jungs jetz hab ich nur noch ein problem und zwar wird der server auch beendet wenn der client geschlossen wird und des liegt ja daran

    while(rc!=SOCKET_ERROR)
       {
        rc=recv(connectedSocket,buf,256,0);
        if(rc==0)
        {
          printf("Server hat die Verbindung getrennt..\n");
          break;
        }
    

    und wenn ich folgendes mach funzt es net un der server spinnt

    while(rc!=SOCKET_ERROR)
       {
        rc=recv(connectedSocket,buf,256,0);
        if(rc==0)
        {
      rc=listen(acceptSocket,10);
      if(rc==SOCKET_ERROR)
      {
        printf("Fehler: listen, fehler code: %d\n",WSAGetLastError());
        return 1;
      }
    
      // Verbindung annehmen
      connectedSocket=accept(acceptSocket,NULL,NULL);
      if(connectedSocket==INVALID_SOCKET)
      {
        printf("Fehler: accept, fehler code: %d\n",WSAGetLastError());
        return 1;
      }
        }
    

    kann man irgiendwie machen das der wieder vor der while schleifen aufs listen springt



  • ja, nimm listen raus aus while.
    Simon



  • sry aber da haste wohl was falsch verstanden des listen is ja eigtl net drin in while ich habs halt mal reingemacht um zu probiern ob der server so nach einem disconnect vom client wieder auf neue verbindungen wartet und das richtige listen und so kommt vor der while nun weiß ich aber net wie ich machen soll das wenn der cleint beendet wird der der server anstatt zu beenden aus der while rausgeht und wieder nach oben zum listen springt...

    goto geht ja nur zb in nem switch wenn ich des richtig verstanden hab also kann ich damit ja net arbeiten



  • Nein, listen wird nur einmal aufgerufen, nicht vor jedem accept .

    Normalerweise sollte so eine Schleife in etwa so aussehen (Pseudo-Code):

    while (true)
    {
        new_socket = accept (s, NULL, 0);
        if (new_socket < 0)
            continue;
    
        // Kommunizieren
        rc = recv (s, buf, len, 0);
        if (rc < 0)
            continue;
    
        // ...
    }
    

    Bei jedem continue springt er dann wieder zum Anfang der Schleife und wartet auf eine neue Verbindung.

    Wenn du richtig gut bist ( 😃 ) kannst du jedes mal, wenn eine Verbindung ankommt, einen eigenen Thread startet, so dass du mehrere Clients verarbeiten kannst.



  • if (rc < 0)
    {
       // fehler
    }
    else if (rc == 0)
    {
       // verbindung von gegenstelle geschlossen
    }
    else
    {
       // daten bekommen...
    }
    

    Nur als Anmekrung...


Anmelden zum Antworten