Code:
int main( int argn, char **arg )
{
if ( argn <= 1 ) help( *arg );
int port = 0;
// zpracovani prikazoveho radku
for ( int i = 1; i < argn; i++ )
{
if ( !strcmp( arg[ i ], "-d" ) )
debug = 1;
if ( !strcmp( arg[ i ], "-h" ) )
help( *arg );
if ( *arg[ i ] != '-' && !port )
{
port = atoi( arg[ i ] );
break;
}
}
if ( !port )
{
zprava( ZPR_INFO, "Chybejici nebo spatne cislo portu!" );
help( *arg);
}
zprava( ZPR_INFO, "Server bude poslouchat na portu: %d.", port );
// vytvoreni socketu
int sock_listen = socket( AF_INET, SOCK_STREAM, 0 );
if ( sock_listen == -1 )
{
zprava( ZPR_CHYBA, "Nelze vytvorit socket.");
exit( 1 );
}
in_addr addr_any = { INADDR_ANY };
sockaddr_in srv_addr;
srv_addr.sin_family = AF_INET;
srv_addr.sin_port = htons( port );
srv_addr.sin_addr = addr_any;
// socket smi znovu okamzite pouzit jiz drive pouzite cislo portu
int opt = 1;
if ( setsockopt( sock_listen, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof( opt ) ) < 0 )
zprava( ZPR_CHYBA, "Nelze nastavit vlastnosti socketu." );
// prirazeni adresy a portu socketu
if ( bind( sock_listen, (const sockaddr * ) &srv_addr, sizeof( srv_addr ) ) < 0 )
{
zprava( ZPR_CHYBA, "Prirazeni adresy selhalo." );
close( sock_listen );
exit( 1 );
}
// aplikace bude naslouchat na zadanem portu
if ( listen( sock_listen, 1 ) < 0 )
{
zprava( ZPR_CHYBA, "Nelze naslouchat na pozadovanem portu." );
close( sock_listen );
exit( 1 );
}
int sock_client = 0;
// jedeme!
while ( 1 )
{
char buf[ 100 ];
// mnozina hadlu
fd_set read_wait_set;
// vynulovani mnoziny
FD_ZERO( &read_wait_set );
// pridani handlu stdin
FD_SET( STDIN_FILENO, &read_wait_set );
// vyber handlu - listen nebo spojeni se serverem?
// cekame na spojeni, nebo na data od serveru?
if ( sock_client )
{
FD_SET( sock_client, &read_wait_set );
}
else
{
FD_SET( sock_listen, &read_wait_set );
// fork();
}
// cekame na data u nektereho handlu
if ( select( MAX( sock_client, sock_listen ) + 1,
&read_wait_set, 0, 0, 0 ) < 0 ) break;
// data na stdin?
if ( FD_ISSET( STDIN_FILENO, &read_wait_set ) )
{
// cteme data ze stdin
int l = read( STDIN_FILENO, buf, sizeof( buf ) );
if ( l < 0 )
zprava( ZPR_CHYBA, "Nelze cist data ze stdin." );
else
zprava( ZPR_LADENI, "Nacteno %d bytu ze stdin.", l );
// posleme data klientovi
l = write( sock_client, buf, l );
if ( l < 0 )
zprava( ZPR_CHYBA, "Nelze zaslat data klientovi." );
else
zprava( ZPR_LADENI, "Odeslano %d bytu klientovi.", l );
}
else if ( FD_ISSET( sock_listen, &read_wait_set ) )
{
sockaddr_in rsa;
int rsa_size = sizeof( rsa );
// prijmeme nove spojeni
sock_client = accept( sock_listen, ( sockaddr * ) &rsa, ( socklen_t * ) &rsa_size );
if ( sock_client == -1 )
{
zprava( ZPR_CHYBA, "Spojeni se nezdarilo." );
close( sock_listen );
exit( 1 );
}
if (fork() !=0)
{
close (sock_client);
continue;
}
else {
if (fork() == 0)
{
uint lsa = sizeof( srv_addr );
// ziskani vlastni IP
getsockname( sock_client, ( sockaddr * ) &srv_addr, &lsa );
zprava( ZPR_INFO, "Moje IP: '%s' port: %d",
inet_ntoa( srv_addr.sin_addr ), ntohs( srv_addr.sin_port ) );
// ziskani IP klienta
getpeername( sock_client, ( sockaddr * ) &srv_addr, &lsa );
zprava( ZPR_INFO, "Klient IP: '%s' port: %d",
inet_ntoa( srv_addr.sin_addr ), ntohs( srv_addr.sin_port ) );
zprava( ZPR_INFO, "Zadejte 'quit' pro ukonceni procesu serveru." );
}
}
}
}
// data od klienta?
else if ( FD_ISSET( sock_client, &read_wait_set ) )
{
// precteme data od klienta
int l = read( sock_client, buf, sizeof( buf ) );
if ( !l )
{
zprava( ZPR_LADENI, "Klient uzavrel spojeni." );
close( sock_client );
sock_client = 0;
break;
}
else if ( l < 0 )
zprava( ZPR_LADENI, "Nelze precist data od klienta." );
else
zprava( ZPR_LADENI, "Precteno %d bytu od klienta.", l );
// vsechna data na stdout
l = write( STDOUT_FILENO, buf, l );
if ( l < 0 )
zprava( ZPR_CHYBA, "Nelze zapsat na stdout." );
// konrola, zda klient nezada o ukonceni spojeni
if ( !strncasecmp( buf, "close", 5 ) )
{
zprava( ZPR_INFO, "Klient zaslal 'close' pozadavek, ukoncujeme spojeni." );
zprava( ZPR_INFO, "Cekame na pripojeni noveho klienta." );
close( sock_client );
sock_client = 0;
}
}
// byl pozadavek na ukonceni prace serveru?
if ( !strncasecmp( buf, "quit", 4 ) )
{
close( sock_client );
zprava( ZPR_INFO, "Byl zadan pozadavek 'quit'. Server konci svou cinnost.\n" );
break;
}
}
close( sock_listen );
return 0;
}