// 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;
}
// Sendet eine Nachricht an alle Clients
// Send's a Message to all clients
/*int sendToAllClients(char* msg)
{
int rc,i;
for(i=0;i<MAX_CLIENTS;i++)
{
if(!clients[i].used)
continue;
rc=send(clients[i].socket,msg,strlen(msg),0);
if(rc==SOCKET_ERROR)
{
printf("Error: Sending to Client %d failed: %d\n",i,WSAGetLastError());
}
}
return 0;
}
*/
// 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 | CREATE_NEW_CONSOLE,
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
// rc==0 => client closed connection
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!
// rc==SOCKET_ERROR => error, close connection!
}
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
// receive data and send it to all clients
}
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
// cleanup
closesocket(acceptSocket);
WSACleanup();
}
else
{
cout << "server PORT" << endl;
}
return 0;
}