Hilfe bei der Umleitung der Konsolenausgabe...

Da Du zweischen Client und Server eine bidirektionale Kommunikation hast, müssen natürlich beide gegenseitig auf sich hören.
-> Der Client schickt dem Server den Befehl zum Starten der Anwendung. Dann empfängt er Daten vom Server.
-> Der Server startet die Anwendung und schickt die Ausgaben an den Client
-> Wenn im Client Daten auf der Konsole eingegeben werden, sendet er diese an den Server.
-> Der Server übergibt die empfangenen Daten an die Anwendung
Und so geht das weiter bis die anwendung beendet ist und der Server den Socket schließt.

Ich habe jetzt leider nicht mehr die Zeit, das weiter auszuformulieren. Probier mal weiter, ich schau' mir dann morgen an, was Du hast.
 
Habe im Client folgendes ergänzt:

Code:
//Eingabe des Befehle...
//Sende Befehl
//Empfange Daten
//Eingabe für den Input Inhalt...
getline(cin, str);
            rc=send(s,str.c_str(),strlen(str.c_str()),0); 
            if(rc==SOCKET_ERROR)
            {
                printf("Error: Sending to Server failed: %d\n",WSAGetLastError()); 
            }
Beim Server habe ich als Kontrolle mehrere Ausgaben hinzugefügt:

Code:
//Auf Ende warten und Messages lesen
    while(dwWaitResult != WAIT_OBJECT_0)
    {
        cout << "Schleife gestartet..." << endl;
        ......

if(dwBytesRead)
                {                               
                    send(s, cReadLine, strlen(cReadLine), 0);
                    cout << "send client...:" << cReadLine << endl;
        .....
Thread Funktion:
Code:
unsigned long __stdcall threadfunc( void *data)
{
    cout << "Thread gestartet..." << endl;
    .....
 
else if (iBytesReceived > 0)
        {
            cout << "buffer empfangen: " << buffer << endl;
             WriteFile(pThreadData->hPipe, buffer, iBytesReceived, &dwBytesWritten, NULL);
        }

Jetzt beschreibe ich detaliert, was beim Server/Client passiert mit Hilfe von test.exe(Input Eingabe).

- starte server auf port 12
- verbinde client mit server
- gebe beim client den befehl test ein
- beim server wird folgendes ausgeben:
Code:
Schleife gestartet...Thread gestartet...

send client...:Eingabe:
Schleife gestartet...
Schleife gestartet...
Schleife gestartet...
Schleife gestartet...
Schleife gestartet...
Schleife gestartet...
//..dauert so lange bis der client was eingibt
- gebe beim client bei der zweiten Eingabe help ein
- muss schnell beim Server pause drücken damit ich die ausgabe sehen kann.
- beim server wird folgendes ausgegeben:
Code:
....
buffer empfangen: helpÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ
Schleife gestartet...
Schleife gestartet...
Schleife gestartet...
Schleife gestartet...
Schleife gestartet...
Schleife gestartet..
....
- Die Schleife geht weiter.
- Gebe beim Client beliebig etwas ein und bekomme verspätet die ausgabe von test.exe

Eingabe:


Ein Problem ist, wieso bekomme ich immer beim client die ausgaben so spät?
Nachdem ich test zum server gesendet habe, hat dieser mit "Eingabe:" von test gesendet, aber im client ist diese Ausgabe nicht gleich ausgegeben worden.

Habe den Client debuggt mit F10, habe den befehl info eingegeben und sofort diese ausgabe bekommen, komisch oder? Sobald ich den client und server normal gestartet habe und den befehl eingegeben habe, musste ich beim nocheinmal enter drücken damit die ausgabe da war genauso wie mit dem oberen Beispiel.

Also langasam weiß ich auch nicht mehr weiter, wenn das nicht klappen sollte dann lasse ich es lieber und der server soll dann nur die ausgabe umleiten.
 
Hallo nochmals, habe den Server wieder zurückgestzt, jetzt kann er nur die Ausgabe zum Client umleiten.

Ich habe nur noch eine letzte Bitte, es funktioniert alles prima, doch die Ausgabe kommt immer beim Client zu spät an woran kann das liegen?
Hat das mit der Länge Buffers zu tun oder mit Timeout...
Mit dem Debugger funktioniert es!

Bitte nochmals um Hilfe

Client:

Code:
#include <stdlib.h> 
#include <stdio.h> 
#include <windows.h> 
#include <winsock.h> 
#include <conio.h> 
#include <string>
#include <iostream>
#include <sstream>
#include <cstdio> 
#include <vector>
#include "format.h"

using namespace std;

#pragma comment(lib,"wsock32.lib")
#pragma comment(lib,"advapi32.lib")


// Startet Winsock und gibt einige Infos zur Version aus 
// Starts winsock and dumps some infos about the version 
int startWinsock() 
{ 
   int rc; 
   WSADATA wsaData; 
   rc=WSAStartup(MAKEWORD(2,0),&wsaData); 
   
   if(rc==SOCKET_ERROR) 
   { 
      printf("Error, exiting!\n"); 
      return rc; 
   }  
   //printf("System Status: %s\n",wsaData.szSystemStatus); 
   return 0; 
} 

// Sucht eine IP anhand eines Strings, der entweder die IP als String 
// oder einen Hostname enthalten kann 
long getAddrFromString(char* hostnameOrIp, SOCKADDR_IN* addr) 
{ 
   long rc; 
   unsigned long ip; 

   HOSTENT* he; 

   if(hostnameOrIp==NULL || addr==NULL) 
      return SOCKET_ERROR; 
   ip=inet_addr(hostnameOrIp); 

   if(ip!=INADDR_NONE)
   { 
      addr->sin_addr.s_addr=ip; 
      return 0; 
   } 
   else 
   { 
      he=gethostbyname(hostnameOrIp); 
      if(he==NULL) 
      { 
         return SOCKET_ERROR; 
      } 
      else 
      { 
         memcpy(&(addr->sin_addr),he->h_addr_list[0],4); 
      } 
      return 0; 
   } 
} 

int main(int argc, char* argv[]) 
{    
    if(argc > 2)
    {
        char* HOST = argv[1];
        int PORT = atoi(argv[2]);

        SOCKET s; 
        SOCKADDR_IN addr; 
        char c; 
        char buf[1024]; 
        char inpBuf[1024]; 
        int inpBufPos=0; 
        fd_set fdSetRead; 
        TIMEVAL timeout; 
        int rc; 


        // start winsock 
        rc=startWinsock(); 
        if(rc==SOCKET_ERROR) 
        return 1; 

        // addr vorbereiten, hostname auflösen 
        // prepare addr, resolve hostname 
        memset(&addr,0,sizeof(SOCKADDR_IN)); 
        addr.sin_family=AF_INET; 
        addr.sin_port=htons(PORT); 
        rc=getAddrFromString(HOST, &addr); 
        if(rc==SOCKET_ERROR) 
        { 
            printf("Error: Cannot resolve Host %s\n", HOST); 
            return 1; 
        } 

        // socket erstellen 
        // create socket 
        s=socket(PF_INET,SOCK_STREAM,0); 
        if(s==INVALID_SOCKET) 
        { 
            printf("Error, cannot create socket: %d\n",WSAGetLastError()); 
            return 1; 
        } 

        // verbinden.. 
        // connect.. 
        printf("Connecting...\n"); 
        rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR)); 
        if(rc==SOCKET_ERROR) 
        { 
            printf("Error: connect failed: %d\n",WSAGetLastError()); 
            return 1; 
        }
        
        cout << endl;
        
        string str; //Eingabe String

        do
        {
            
            cout << "Eingabe:>";
            
            getline(cin, str);

            

            if(str == "exit")
            {
                closesocket(s); 
                WSACleanup(); 
                return 0;
            }

            else if(str == "close")
            {
                rc=send(s,str.c_str(),strlen(str.c_str()),0); 
                if(rc==SOCKET_ERROR)
                {
                    printf("Error: Sending to Server failed: %d\n",WSAGetLastError()); 
                } 
                closesocket(s); 
                WSACleanup(); 
                return 0;
            }
            //Sende Befehl...
            rc=send(s,str.c_str(),strlen(str.c_str()),0); 
            if(rc==SOCKET_ERROR)
            {
                printf("Error: Sending to Server failed: %d\n",WSAGetLastError()); 
            } 
            
                        
            // fd_set und timeout vorbereiten 
            FD_ZERO(&fdSetRead); 
            FD_SET(s,&fdSetRead); 
            timeout.tv_sec=0; 
            timeout.tv_usec=0; 

            // prüfen ob ein socket bereit ist, da timeout=0 kehrt die funktion 
            // sofort wieder zurück nach dem aufruf. 
            // achtung: das timeout auf 0 setzen oder als paremeter NULL mitgeben 
            // ist NICHT das gleiche. auf 0 gesetzt kehrt sofort zurück, während NULL blockt. 
            while((rc=select(0,&fdSetRead,NULL,NULL,&timeout))>0) 
            { 
                rc=recv(s,buf,1024,0); 
                // server hat die verbindung beendet ? 
                if(rc==0) 
                { 
                    printf("Server closed connection!\n"); 
                    return 1; 
                // fehler: beenden! 
                } 
                else if(rc==SOCKET_ERROR) 
                { 
                    printf("Error: recv failed: %d\n",WSAGetLastError()); 
                    return 1; 
                } 
                // empfangene daten ausgeben 
                buf[rc]='\0'; 
                cout << buf << endl;
            } 
            
            
                
        }while(rc!=SOCKET_ERROR);//Ende do-while

        // aufräumen 
        // cleanup.. 
        closesocket(s); 
        WSACleanup(); 
        cout << "Client shutdown, press any key to exit" << endl;
        getch(); 

       }
       else    
       {
           cout << "Client HOST PORT" << endl;
       }
       return 0; 

}


Server:

Code:
// max. Anzahl Clients 
// Max. number of clients 
#define MAX_CLIENTS 20


// Der Standartwert für FD_SETSIZE ist 64, dieser kann aber verändert 
// werden indem man FD_SETSIZE auf einen anderen Wert setzt bevor man 
// winsock2.h includiert. 
// FD_SETSIZE auf die max. Anzahl Clients setzten 
#define FD_SETSIZE   MAX_CLIENTS 

// includes... 
#include <stdlib.h> 
#include <stdio.h> 
#include <windows.h> 
#include <winsock.h> 
#include <conio.h> 
#include <string>
#include <iostream>
#include "convert.h"
#include "registry.h"

#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib,"user32.lib")

using namespace std;

// Stellt eine Verbindung mit einem Client dar 
// Represents a connection with a Client 
struct Connection 
{ 
   Connection() 
   { 
      used=false; 
      socket=INVALID_SOCKET; 
   } 
   void set(SOCKET s, SOCKADDR_IN addr) 
   { 
      this->socket=s; 
      this->addr=addr; 
      this->used=true; 
   } 
   void erase() 
   { 
      this->used=false; 
      this->socket=INVALID_SOCKET; 
   } 
   bool used;   // connection benutzt ? / connection slot used ? 
   SOCKET socket; // socket 
   SOCKADDR_IN addr; // client addr 
}; 

// clients 
Connection clients[MAX_CLIENTS]; 

// Sucht den nächsten freien Platz im clients Array 
// -1 = kein platz frei 
// Searches the next free slot in the clients array 
// -1 = no free slot 
int getFreeClientSlot() 
{ 
   for(int i=0;i<MAX_CLIENTS;i++) 
   { 
      if(clients[i].used==false) 
         return i; 
   } 
   return -1; 
} 


// Startet Winsock und gibt einige Infos zur Version aus 
// Starts winsock and dumps some infos about the version 
int startWinsock() 
{ 
   int rc; 
   WSADATA wsaData; 
   rc=WSAStartup(MAKEWORD(2,0),&wsaData); 
   
   if(rc==SOCKET_ERROR) { 
      printf("Error, exiting!\n"); 
      return rc; 
   }   
   printf("System Status: %s\n",wsaData.szSystemStatus); 
   return 0; 
} 


#define MAX_LINE_LENGTH 1024


BOOL ProcessCommandLine(char * pcCommandLine, SOCKET s)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    HANDLE hReadPipe, hWritePipe;
    DWORD dwWaitResult = WAIT_TIMEOUT, dwBytesRead, dwExitCode, dwSizeLow, dwSizeHigh, dwError;
    char cReadLine[MAX_LINE_LENGTH];
    BOOL bDoRead = TRUE, bOK = TRUE;
    MSG AppMsg;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);


    //Pipes erzeugen
    sa.nLength=sizeof(sa);
    sa.bInheritHandle=TRUE;
    sa.lpSecurityDescriptor=NULL;
    bOK = CreatePipe(&hReadPipe, &hWritePipe, &sa, 1048576);
    if(!bOK)
    {
        //FEHLER
        dwError = GetLastError();
        bOK = FALSE;
        goto PROCESS_END_NOPIPE;
    }

    //Pipes eintragen
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    si.hStdOutput = hWritePipe;                        //Schreib-Ende der Pipe an Prozess übergeben
    si.hStdError = hWritePipe;                        //Schreib-Ende der Pipe an Prozess übergeben
    si.wShowWindow = SW_SHOWMINNOACTIVE;

    //Prozess starten
    bOK = CreateProcess(NULL,
                        pcCommandLine,
                        NULL,
                        NULL,
                        TRUE,
                        NORMAL_PRIORITY_CLASS,
                        NULL,
                        NULL,
                        &si,
                        &pi);

    if(!bOK)
    {
        //FEHLER
        dwError = GetLastError();
        goto PROCESS_END_NOPROC;
    }

    //Auf Ende warten und Messages lesen
    while(dwWaitResult != WAIT_OBJECT_0)
    {
        dwWaitResult = WaitForSingleObject(pi.hProcess, 10);
        while(dwSizeLow = GetFileSize(hReadPipe, &dwSizeHigh))
        {
            ZeroMemory(cReadLine, MAX_LINE_LENGTH);
            //Aus dem Leseende der Pipe die Progzessausgaben lesen
            if(bDoRead = ReadFile(hReadPipe, cReadLine, MAX_LINE_LENGTH - 1, &dwBytesRead, NULL))
            {
                if(dwBytesRead)
                {
                    //**** hier Programmausgabe verarbeiten (z.B. send) *******
                    send(s, cReadLine, strlen(cReadLine), 0);
                }
            }
            else
            {
                bOK = FALSE;
                dwError = GetLastError();
            }
        }
        //Applikations-Messagequeue verarbeiten
        if(PeekMessage(&AppMsg, 0, 0, 0, PM_NOREMOVE))
        {
            GetMessage(&AppMsg, 0, 0, 0);
            TranslateMessage(&AppMsg);
            DispatchMessage(&AppMsg);
        }
    }

    if(bOK)
    {
        bOK = GetExitCodeProcess(pi.hProcess, &dwExitCode);
        if(bOK)
        {
            if(dwExitCode != 0)
            {
                //Prozess kehrt mit Ergebnis != 0 zurück
                bOK = FALSE;
            }
        }
        else
        {
            //FEHLER im GetExitCodeProcess
            dwError = GetLastError();
            bOK = FALSE;
        }
    }

    //Close handles
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

PROCESS_END_NOPROC:
    CloseHandle(hWritePipe);
    CloseHandle(hReadPipe);

PROCESS_END_NOPIPE:
    return bOK;
}




int main(int argc, char* argv[]) 
{ 
    if(argc > 1)
    {
        //Startet auf dem übergebenem PORT
        int PORT = atoi(argv[1]);
    
       // SOCKET welcher neue Verbindungen annimmt 
       // SOCKET which accepts new connections 
       SOCKET acceptSocket; 
       SOCKADDR_IN addr; 
       int rc,addrsize=sizeof(SOCKADDR_IN); 
       unsigned int i,j; 
       // fd_set 
       fd_set fdSetRead; 
       // timout für select() / timeout for select() 
       timeval selectTimeout; 
       // temporär benutz für neue verbindungen 
       // temporary used for new connections 
       Connection newConnection; 
       // buffer 
       char buf[1024]; 

       // clients array leeren / clear clients array 
       memset(clients,0x0,sizeof(Connection)*MAX_CLIENTS); 

       // start winsock 
       rc=startWinsock(); 
       if(rc==SOCKET_ERROR) 
          return 1; 

       // socket erstellen / create socket 
       acceptSocket=socket(PF_INET,SOCK_STREAM,0); 
       if(acceptSocket==INVALID_SOCKET) 
       { 
          printf("Error, cannot create socket: %d\n",WSAGetLastError()); 
          return 1; 
       } 

       // sockt an port 1234 binden / bind socket to port 1234 
       memset(&addr,0,sizeof(SOCKADDR_IN)); 
       addr.sin_family=AF_INET; 
       addr.sin_port=htons(PORT); 
       addr.sin_addr.s_addr=INADDR_ANY; 
       rc=bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN)); 
       if(rc==SOCKET_ERROR) 
       { 
          printf("Error, bind() failed: %d\n",WSAGetLastError()); 
          return 1; 
       } 

       // auf verbindungen warten / listen for connections 
       rc=listen(acceptSocket,10); 
       if(rc==SOCKET_ERROR) 
       { 
          printf("Error,listen() failed: %d\n",WSAGetLastError()); 
          return 1; 
       } 


       // The parameter readfds identifies the sockets that are to be checked for readability. 
       // If the socket is currently in the listen state, it will be marked as readable if an 
       // incoming connection request has been received such that an accept is guaranteed to 
       // complete without blocking. 
        
       while(1) 
       { 

          // fd_set leeren / clear fd_set 
          FD_ZERO(&fdSetRead); 
           
          // den socket welcher verbindungen annimmt hinzufügen 
          // add the SOCKET which accepts new connections 
           
          FD_SET(acceptSocket,&fdSetRead); 
          // alle clients hinzufügen 
          // add all clients 
          for(i=0;i<MAX_CLIENTS;i++) 
          { 
             if(clients[i].used) 
                FD_SET(clients[i].socket,&fdSetRead); 
          } 

          // warten bis irgend ein socket bereit ist, wenn timout NULL ist kehrt select() 
          // erst zurück wenn ein socket bereit ist, select() blockt also in diesem falle 
          // wait until any socket is ready (timeout = NULL, block until one socket is ready) 
          rc=select(0,&fdSetRead,NULL,NULL,NULL); 

          // abbrechen bei einem fehler 
          // break on error 
          if(rc<1) 
             break; 

          printf("select() returned %d ready sockets\n",rc); 
           
          for(i=0;i<fdSetRead.fd_count;i++) 
          { 
           
             // acceptSocket ? 
             if(fdSetRead.fd_array[i]==acceptSocket) 
             { 
                // verbindung annehmen / accept new connection 
                newConnection.socket=accept(acceptSocket,(SOCKADDR*)&newConnection.addr,&addrsize); 
                rc=getFreeClientSlot(); 
                if(rc==-1) 
                { 
                   printf("Cannot accept new clients\n"); 
                   continue; 
                } 
                // zu den clients hinzufügen 
                // add to clients 
                clients[rc]=newConnection; 
                clients[rc].used=true; 
                printf("New Client accepted from %s\n",inet_ntoa(newConnection.addr.sin_addr)); 
                continue; 
             } 
              
             // ein client ? 
             // a client ? 
             for(j=0;j<MAX_CLIENTS;j++) 
             { 
                if(!clients[j].used) 
                   continue; 

                if(clients[j].socket==fdSetRead.fd_array[i]) 
                { 
                   rc=recv(clients[j].socket,buf,1023,0); 
                   buf[rc]='\0'; 
                   // rc==0 => client hat die verbindung beendet 
                   if(rc==0) { 
                      printf("Client %d (%s): closed connection\n",j,inet_ntoa(clients[j].addr.sin_addr)); 
                      closesocket(clients[j].socket); 
                      clients[j].erase(); 
                      continue; 
                   // rc==SOCKET_ERROR => fehler, verbindung beenden! 
                   } 
                   else if(rc==SOCKET_ERROR) 
                   { 
                      printf("Client %d (%s): Error %d\n",j,inet_ntoa(clients[j].addr.sin_addr),WSAGetLastError()); 
                      printf("Client %d (%s): Server aborts connection\n",j,inet_ntoa(clients[j].addr.sin_addr)); 
                      closesocket(clients[j].socket); 
                      clients[j].erase(); 
                      continue; 
                   // daten empfangen und an alle clients senden 
                   } 
                   else 
                   { 
                       printf("Client %d (%s): Befehl: '%s' \n",j,inet_ntoa(clients[j].addr.sin_addr),buf); 
                      //sendToAllClients(buf); 
                      
                      string command = buf;
                      if(command.find(' ') != string::npos)
                      {                          
                          int pos = command.find(' ');   
                          int lang = command.length();
                            string task = command.substr(0,pos);
                          string para = command.substr(pos+1,lang);

                          string str;
                          str += '"';
                          str += reg.xmd_GetValue("bin");
                          str += "\\";
                          str += task;
                          str += ".exe";
                          str += '"';
                          str += " " + para;
                                                    
                          cout << "Erfolgreich: " << ProcessCommandLine(cvt.StringToChar(str), clients[j].socket) << endl;
                      }
                      
                      else
                      {                            
                         if(command == "close")                        
                         {
                             //rc=send(clients[i].socket,msg,strlen(msg),0); 
                             //  rc=send(clients[j].socket,task.c_str(),strlen(task.c_str()),0); 
                             closesocket(acceptSocket); 
                             WSACleanup();
                         }                         
                         cout << "Erfolgreich: " << ProcessCommandLine(cvt.StringToChar(command), clients[j].socket) << endl;
                      }          

                   } 
                } 
             } 
          }

          cout << "-----------------------------------" << endl;
       }//Ende while

       // aufräumen 
       closesocket(acceptSocket); 
       WSACleanup();        
    }
    else 
    {
        cout << "server PORT" << endl;
    }
    
    return 0;   
}
 
Sorry, aber da kann ich Dir leider nicht helfen. Mit der Netzwerkprogrammierung kenne ich mich nämlich nicht sehr gut aus.
Aber was meinst Du mit 'kommt zu spät an'?
 
Also es kommt die Ausgabe der einzelnen *.exe die umgeleitet wurden zu spät beim client an, d.h. wenn ich ein befehl eingebe wie z.B. info dann Enter drücke kommt nicht nach dem ersten sondern nach dem zweiten Enter die Ausgabe. Eigentlich sollte es so aussehen Eingabe = Enter = Ausgabe.

Vielleicht kannst du es mal dir ausprobieren, du müsstes eine dritte test.exe erstellen die einfach mit cout etwas ausgibt dann alle drei Programme ins gleiche Verzeichnis kopieren.
 

Neue Beiträge

Zurück