Lidt af et problem
Hej...Jeg er igang med at lave et klient-server program i c++ på en redhat linux box. Jeg bruger g++ kompileren. Men jeg to problemer i mit program, som jeg ikke rigtig kan se hvordan jeg løser. Koden er noget lang, så derfor kommer jeg først lige med problemet. (er lidt ør i hovedet, det er sent og jeg er møgtræt)
Problemet er at serveren, efter den har modtaget en connection fra en klient, kan den ikke modtage flere igen, jeg tror det er en fejl i min close() statement til fejl_discriptoren. Men jeg har prøvet at rode lidt med det, uden held. Det andet problem ligger i at når jeg SEND'er eller RECV'er får jeg for mange overskyldende tegn med i min string. Muligvis ligger problemet i min stoc() funktion (string to char). Men jeg har igaan svært at se det.
Lidt beskrivelse af filerne g4apt.h indeholder nogle hjælpe funnktioner, blandet stoc() (string to char) og ctos() (char to string ). G4socket.h er en, man kan kalde den, wrappeclass til klient/server sockets. Mens g4.cc indeholder main() som initialiserings punkterne til serveren og klienten. Fra prompten er det (i linux) for klienten ./g4.o klient <server> <port>, mens for serveren er det ./g4.o <port>
Her er nogle gode pionts at score, eftersom jeg er ved at blive helt skeløjet af al den kaffe jeg har indtaget.
Men her er koden... Er I klar:
FILEN: G4APT.H
#include <string>
#include <iostream>
using namespace std;
string ctos( char *chartekst )
{ // PRE: string = ctos( *char );
// POST: returnere chararray typecastet til string
return (string)chartekst;
}
/*
const char* stoc( std::string stringtekst)
{
return stringtekst.c_str();
}
*/
char* stoc( string stringtekst )
{ // PRE: char = stoc( string );
// POST: returnere stringen som et chararray
int length = stringtekst.length(),
i;
char *chartekst = (char*)malloc( length );
for( i=0; i<length; i++ )
{
chartekst[ i ] = stringtekst[ i ];
}
//chartekst[ i+1 ] = '\0';
return chartekst;
}
/*
string strapp( string stringtekst, char tilfoej )
{ // PRE: string strapp( string, char )
// POST: Returnere string hvor char til tilføjet til stringtekst
return ( stringtekst+=tilfoej );
}
*/
FILEN: G4SOCKET.H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <string>
#include <iostream>
#include "g4apt.h"
class g4socket
{ public:
string fejlbesked;
g4socket();
int find_server_navn( char* &_server, struct hostent* &_server_navn );
int init_klient_socket( int &_server_nummer );
int init_server_socket( int &_server_nummer );
int saet_server_socketadresse( struct sockaddr_in &_adresse, int &_port );
int saet_klient_socketadresse( struct sockaddr_in &_adresse, int &_port, struct hostent* &_server_navn );
int lav_forbindelse( int &_server_nummer, struct sockaddr_in &_adresse );
int bind_server( int &_server_nummer, struct sockaddr_in &_server_adresse );
int lyt( int &_server_nummer, int &_antal );
int modtag( int &_klient_nummer, int &_server_nummer, struct sockaddr_in &_klient_adresse );
int send_besked( int &_server_nummer, string &_besked );
int modtag_besked( int &_server_nummer, string &_modtaget );
private:
int tilstand;
};
g4socket::g4socket()
{ tilstand = 0;
}
int g4socket::find_server_navn( char* &_server, struct hostent* &_server_navn )
{ if( tilstand != 0 )
{ fejlbesked = "Et objekt af klassen g4socket er ikke oprettet";
return 1;
}
else
if( (_server_navn = gethostbyname( _server )) == NULL )
{ fejlbesked = "Kunne finde serverens navn";
return 1;
}
else
{ tilstand = 1;
return 0;
}
}
int g4socket::init_klient_socket( int &_server_nummer )
{ if( tilstand != 1 )
{ fejlbesked = "Serverens navn er ikke blevet fundet endnu";
return 1;
}
else
if( (_server_nummer = socket( AF_INET, SOCK_STREAM, 0 )) == -1 )
{ fejlbesked = "Der kunne ikke initialiseres en socket";
return 1;
}
else
{ tilstand = 2;
return 0;
}
}
int g4socket::init_server_socket( int &_server_nummer )
{ if( tilstand != 0 )
{ fejlbesked = "Serverens navn er ikke blevet fundet endnu";
return 1;
}
else
if( (_server_nummer = socket( AF_INET, SOCK_STREAM, 0 )) == -1 )
{ fejlbesked = "Der kunne ikke initialiseres en socket";
return 1;
}
else
{ tilstand = 2;
return 0;
}
}
int g4socket::saet_server_socketadresse( struct sockaddr_in &_adresse, int &_port )
{ if( tilstand != 2 )
{ fejlbesked = "Der kunne ikke sættes en adresse op";
return 1;
}
else
{ _adresse.sin_family = AF_INET;
_adresse.sin_port = htons( _port );
_adresse.sin_addr.s_addr = INADDR_ANY;
memset( &(_adresse.sin_zero), '\0', 8 );
tilstand = 3;
return 0;
}
}
int g4socket::saet_klient_socketadresse( struct sockaddr_in &_adresse, int &_port, struct hostent* &_server_navn )
{ if( tilstand != 2 )
{ fejlbesked = "Der kunne ikke sættes en adresse op";
return 1;
}
else
{ _adresse.sin_family = AF_INET;
_adresse.sin_port = htons( _port );
_adresse.sin_addr = *(( struct in_addr *)_server_navn->h_addr);
memset( &(_adresse.sin_zero), '\0', 8 );
tilstand = 3;
return 0;
}
}
int g4socket::lav_forbindelse( int &_server_nummer, struct sockaddr_in &_adresse )
{ if( tilstand != 3 )
{ fejlbesked = "Forbindelsens egenskaber er ikke blevet sat op";
return 1;
}
else
if( connect( _server_nummer, (struct sockaddr *)&_adresse, sizeof( sockaddr) ) == -1 )
{ fejlbesked = "Der kunne ikke oprettes en forbindelse";
return 1;
}
else
{ tilstand = 10;
return 0;
}
}
int g4socket::bind_server( int &_server_nummer, struct sockaddr_in &_server_adresse )
{ if( tilstand != 3 )
{ fejlbesked = "Serveren adresse er ikke blevet sat op";
return 1;
}
else
if( bind( _server_nummer, (struct sockaddr *)&_server_adresse, sizeof( struct sockaddr )) == -1 )
{ fejlbesked = "Serveren kunne ikke blive bundet";
return 1;
}
else
{ tilstand = 4;
return 0;
}
}
int g4socket::lyt( int &_server_nummer, int &_antal )
{ if( tilstand != 4 )
{ fejlbesked = "Serveren er ikke blevet bundet endnu";
return 1;
}
else
if( listen( _server_nummer, _antal ) == -1 )
{ fejlbesked = "Serveren kunne ikke blive sat til at lytte";
return 1;
}
else
{ tilstand = 5;
return 0;
}
}
int g4socket::modtag( int &_klient_nummer, int &_server_nummer, struct sockaddr_in &_klient_adresse )
{ if( tilstand != 5 )
{ fejlbesked = "Serveren er ikke blevet sat til at lyttet endnu";
return 1;
}
else
{ socklen_t sin_size = sizeof( struct sockaddr_in );
if( ( _klient_nummer = accept( _server_nummer, (struct sockaddr *)&_klient_adresse, &sin_size )) == -1 )
{ fejlbesked = "Serveren kunne ikke modtage klienten";
return 1;
}
else
{ tilstand = 10;
return 0;
}
}
}
int g4socket::send_besked( int &_server_nummer, string &_besked )
{ if( tilstand != 10 )
{
fejlbesked = "Der er ikke oprettet en klient eller server";
return 1;
}
else
{ if( send( _server_nummer, stoc( _besked ), strlen( stoc( _besked ) )+1, 0 ) == -1 )
{ fejlbesked = "Fejl ved afsending af beskeden";
return 1;
}
else
return 0;
}
}
int g4socket::modtag_besked( int &_server_nummer, string &_modtaget )
{ if( tilstand != 10 )
{ fejlbesked = "Der er ikke oprettet en klient eller server";
return 1;
}
else
{ int pakke_stoerrelse = 1000,
modtaget_laengde = 0,
faerdig = 0,
modtaget_bytes,
i;
char *_besked = (char *)malloc( pakke_stoerrelse );
while( !faerdig && ( (modtaget_bytes = recv( _server_nummer, _besked+modtaget_laengde, pakke_stoerrelse+modtaget_laengde, 0 )) >= 0 ) )
{ modtaget_laengde += modtaget_bytes;
for( i=(modtaget_laengde-modtaget_bytes); i<modtaget_laengde; i++ )
if( _besked[ i ] == '\0' )
faerdig = 1;
if( (pakke_stoerrelse-modtaget_laengde)<100 )
{ pakke_stoerrelse += 1000;
_besked = (char *)realloc( _besked, pakke_stoerrelse );
}
}
_modtaget = ctos( _besked );
return 0;
}
}
FILEN: G4.CC
#include <stdlib.h> // exit
#include <iostream> // cin/cout
#include <string> // strings
// Egen klasser
#include "g4socket.h" // Sockets
// Forward erklæringer
int numerisk_port( char* _port ); // Isdigit()af et char*
int server( char* _port ); // Init af server
int klient( char* _server, char* _port ); // Init af klient
void main( int antal_argumenter, char *argumenter[] )
{ string fejl = "\nGenerel brug: main klient hostname port ELLER main server port\n";
if( antal_argumenter<3 || antal_argumenter>4 )
{ cout <<fejl <<endl;
exit( 1 );
}
else if( strcmp(argumenter[ 1 ], "server") == 0 && antal_argumenter == 3 )
{ int init_server = server( argumenter[ 2 ] );
if( init_server == 0 )
cout <<endl <<"Serveren lytter på:" <<endl
<<"Port: " <<argumenter[ 2 ] <<endl <<endl;
else if( init_server == 1 )
cout <<endl <<"Serveren kunne ikke initialiseres!" <<endl;
else
cout <<endl <<"Fejl ved initialisering af serveren" <<endl;
}
else if( strcmp(argumenter[ 1 ], "klient") == 0 && antal_argumenter == 4 )
{ int init_klient = klient( argumenter[ 2 ], argumenter[ 3 ] );
if( init_klient == 0 )
cout <<endl <<"Klienten lytter til:" <<endl
<<"Serveren: " <<argumenter[ 2 ] <<endl
<<"Port: " <<argumenter[ 3 ] <<endl <<endl;
else if( init_klient == 1 )
cout <<endl <<"Klienten kunne ikke initialiseres!" <<endl;
else
cout <<endl <<"Fejl ved initialisering af klienten" <<endl;
}
else
{ cout <<fejl <<endl;
exit( 1 );
}
}
int numerisk_port( char* _port )
{ // PRE: En char*
// POST: int 0 hvis char* er numerisk og int 1 hvis fejl.
int i=0;
while( i<strlen( _port ) )
{ if( isdigit(_port[ i ]) != 0 )
i++;
else
return 1;
}
return 0;
}
int server( char* _port )
{ int testport = numerisk_port( _port );
if( testport == 0 )
{ int port = atoi( _port );
g4socket g4server;
string besked;
int antal = 100; //antallet af hvor mange må stå i kø på serveren
struct sockaddr_in server_adresse;
struct sockaddr_in klient_adresse;
int server_nummer;
int klient_nummer;
if( g4server.init_server_socket( server_nummer ) != 0 )
{ cout <<endl <<g4server.fejlbesked <<endl;
return 1;
}
else
{ if( g4server.saet_server_socketadresse( server_adresse, port ) != 0 )
{ cout <<endl <<g4server.fejlbesked <<endl;
return 1;
}
else
{ if( g4server.bind_server( server_nummer, server_adresse ) != 0 )
{ cout <<endl <<g4server.fejlbesked <<endl;
return 1;
}
else
{ if( g4server.lyt( server_nummer, antal ) != 0 )
{ cout <<endl <<g4server.fejlbesked <<endl;
return 1;
}
else
{ signal( SIGCHLD, SIG_IGN );
while( 1 )
{ if( g4server.modtag( klient_nummer, server_nummer, klient_adresse ) != 0 )
{ cout <<endl <<g4server.fejlbesked <<endl;
return 1;
}
else
{ cout <<"Server har modtaget en forbindelse fra " <<inet_ntoa( klient_adresse.sin_addr ) <<endl;
if( !fork() )
{ close( server_nummer );
if( g4server.modtag_besked( klient_nummer, besked ) != 0 )
{ cout <<endl <<g4server.fejlbesked <<endl;
return 1;
}
else
cout <<endl <<besked <<endl;
besked = "emailadresse";
if( g4server.send_besked( klient_nummer, besked ) != 0 )
{ cout <<endl <<g4server.fejlbesked <<endl;
return 1;
}
close( klient_nummer );
return 0;
}
}
close( klient_nummer );
}
}
}
}
}
return 0;
}
else if( testport == 1 )
{ cout <<endl <<"Det angivne port nummer er ikke et tal" <<endl;
return 1;
}
else
{ cout <<"Fejl ved port tjeck" <<endl;
return 1;
}
}
int klient( char *_server, char* _port )
{ int testport = numerisk_port( _port );
if( testport == 0 )
{ int port = atoi( _port );
g4socket g4klient;
string besked; //BESKEDER I HER
struct hostent* server_navn;
struct sockaddr_in server_adresse;
int server_nummer;
if( g4klient.find_server_navn( _server, server_navn ) != 0 )
{ cout <<endl <<g4klient.fejlbesked <<endl;
return 1;
}
else
{ if( g4klient.init_klient_socket( server_nummer ) != 0 )
{ cout <<endl <<g4klient.fejlbesked <<endl;
return 1;
}
else
{ if( g4klient.saet_klient_socketadresse( server_adresse, port, server_navn ) != 0 )
{ cout <<endl <<g4klient.fejlbesked <<endl;
return 1;
}
else
{ if( g4klient.lav_forbindelse( server_nummer, server_adresse ) != 0 )
{ cout <<endl <<g4klient.fejlbesked <<endl;
}
else
{ // DER SKAL BYGGES ET LOOP OP SÅ MAN KAN KOMME UD
besked = "request";
if( g4klient.send_besked( server_nummer, besked ) != 0 )
{ cout <<endl <<g4klient.fejlbesked <<endl;
return 1;
}
if( g4klient.modtag_besked( server_nummer, besked ) != 0 )
{ cout <<endl <<g4klient.fejlbesked <<endl;
return 1;
}
else
cout <<endl <<besked <<endl;
}
}
}
}
close( server_nummer );
return 0;
}
else if( testport == 1 )
{ cout <<endl <<"Det angivne port nummer er ikke et tal" <<endl;
return 1;
}
else
{ cout <<"Fejl ved port tjeck" <<endl;
return 1;
}
}