Eingabe und Ausgabe gleichzeitig in Konsole?



  • Huhu!
    Ich möchte einen Kommandozeilen Basierten dedicated Server für ein Spiel schreiben. (Einmal für Linux, eventuel portier ich ihn auch nach Windows rüber)

    Ich möchte es so machen, dass man in der Konsole ein log sieht (Spieler betritt den Server, chatnachrichten etc..) gleichzeitig möchte ich aber auch befehle in dieser Konsole absetzen können, z.B. um mitzuchatten, einen Spieler zu kicken oder das Level zu wechseln.

    Wie realisiert man die Ausgabe und Eingeibe zugleich? In vielen Kommandozeilen basierten Serverprogrammen sieht man sowas ja öfters.



  • So, ich poste hier mal nen alten Code, bitte nicht schlagen wegen der unordentlichkeit, war eines der ersten Programme, basiert auf Winsock, vlt hilft es dir 😉

    #include <winsock2.h>
    #include <iostream>
    #include <conio.h> 
    #include <string>
    
    using namespace std;
    
    int startWinsock(void);
    char* HostByName();
    
    int main()
    {
      long rc;
      SOCKET s;
      SOCKADDR_IN addr;
      char buf[1302];
      FD_SET fdSet;
      char buffer;
      string input;
    
      int choice;
      char IP[18];
    
      timeval timeout;
    
      timeout.tv_sec = 0;
      timeout.tv_usec = 1;
    
      rc=startWinsock();
      if(rc!=0)
      {
        printf("Fehler: startWinsock, fehler code: %d\n",rc);
        return 1;
      }
      else
      {
        printf("Winsock gestartet!\n");
      }
    
      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");
      }
      cout << "-----------------------------" << endl ;  
      cout << "Chat 2.0 *Von Christopher P.*" << endl ;
      cout << "-----------------------------" << "\n\n" ;
    
      memset(&addr,0,sizeof(SOCKADDR_IN)); 
      addr.sin_family=AF_INET;
      addr.sin_port=htons(1234);   
    
      cout << "Wollen Sie einen Hostnamen oder eine IP-Addresse eingeben ? \n[1]->Hostname\n[2]->IP-Addresse\n\n" ;
      cin >> choice;
      while(true)
      {
          if(choice == 1)
          {
              strcpy(IP, HostByName());         
              break;        
          }
    
          else if(choice == 2)
          {
              cout << "\n\nInput : "; 
              cin >> IP; 
    
              break;      
          }
    
          else
          {
              cout << "Falsche Eingabe!" << endl;    
              continue;
          }
      }
    
      addr.sin_addr.s_addr = inet_addr(IP);
    
      rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR));
      if(rc==SOCKET_ERROR)
      {
        printf("Fehler: connect gescheitert, fehler code: %d\n",WSAGetLastError());
        return 1;
      }
      else
      {
        cout << "--> Verbunden mit [" << IP << "]...\n\n\n" << endl;
        printf("(Um bereits eingegebenes wieder zu loeschen druecken Sie ESCAPE)\n");
        printf("(Um die Verbindung zu trennen 'disconnect' eingeben!)\n");
      }
    
      while(1)
      {
    
            FD_ZERO(&fdSet);        
            FD_SET(s,&fdSet);
    
            rc=select(0,&fdSet,NULL,NULL,(timeval*)&timeout);
    
                if(rc==SOCKET_ERROR)
                {
                    cout << "select() error , code : " << WSAGetLastError << endl;
                }
    
                if(FD_ISSET(s,&fdSet))
                {
    
                        rc=recv(s,buf,1302,0);
    
                        if(rc==0 || rc==SOCKET_ERROR)
                        {
                            cout << "Verbindung beendet" << endl;
                            closesocket(s); 
                            break;
                        }   
    
                        else
                        {
    
                            buf[rc]='\0';
                            cout << "\n" << buf ;  
                            cout << "\n->Tippe eine Nachricht ein! : \n" << input;
                        }                                                                   
                }
    
         if(kbhit()) 
         {       
            char buffer = getch();  
    
            if (buffer != 0)
            {
                if (buffer != 13 && buffer != 8) 
                { 
                    input.push_back(buffer);
                    cout << buffer;
                }
    
                if (buffer != 8 && buffer == 27)
                {
                    input.clear();
                    cout << "\n->Tippe eine Nachricht ein! : \n";                
    
                }
    
                if (buffer == 13 && buffer != 8)  
                {    
                      send(s,input.c_str(),1024,0);
    
                }
    
                if (input == "disconnect" && buffer == 13)
                {
    
                      closesocket(s);    
                      WSACleanup();    
                      break;
                }
    
                if (buffer == 13 && buffer != 8)  
                {    
    
                      input.clear();
                }            
    
              }  
           }         
       }
    
      cout << "\n\n\n -> Verbindung beendet!" << "\n\n Zum Beendet bitte eine Taste druecken..." << endl;
      getch();
    
      WSACleanup();
      return 0;
    }
    
    int startWinsock(void)
    {
      WSADATA wsa;
      return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    
    char* HostByName()
    {
      HOSTENT* he;
      char hostname[256];      
      int i=0;
      IN_ADDR addr;  
    
      cout << "\n\nInput : ";  
      cin >> hostname;
    
      he=gethostbyname(hostname);
    
      cout << "\nHostname: " << he->h_name << endl;
    
      while(he->h_addr_list[i])  
      {
    	  addr.s_addr = * ( (long*) he->h_addr_list[i++] );
    
    	  cout << "Ip Address: " << inet_ntoa(addr) << endl;
      }
    
      return inet_ntoa(addr);
    }
    

    Ich hab das damals so geregelt, das ich den Tastaturbuffer auslese, aber auch nur falls was drin ist, damit konnte ich mir ein cin>> sparen, welches das gesanmte Programm aufhält, oder du nimmst Threads, würde ich dir in der Konsole aber von abraten 😉
    So das ist zwar nur Client aber es sollte dir helfen, sach Bescheid wenn du auch den ServerQuellcode haben willst, wie gesagt ist kein guter Code... xD

    Gruß Chris


Anmelden zum Antworten