PDA

Visualizza la versione completa : [C++] Comunicazione client/server Winsock e caratteri indesiderati


MRj92
26-10-2007, 22:32
Buona sera ragazzi!

Sto provando a creare un prgramma client/server ma non riesco a farlo funzionare!

Allora, io vorrei:




Server attende il client;
Client si connette;
Server gli da il benvenuto ;
Client risponde;

do{
Server pronto a ricevere comandi;
Client da un comando;
Server conferma l'arrivo dei messaggi;
Server lo elabora;
}while(messaggio == "exit")



Io uso un protocollo TCP/IP sulla porta 1111 ma il server restituisce messaggi strani. Al primo mex aggiunge caratteri strani, al secondo altri caratteri indecifrabili e alla terza volta non risponde pi!

Server:


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
SOCKET ServerSocket,ClientSocket;
bool isClientConnected = false;
bool isServerListener = true;

WSADATA wsaInfo;
WSAStartup(MAKEWORD(2,2), &wsaInfo);

ServerSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

//if(ServerSocket == INVALID_SOCKET) throw Error;

SOCKADDR_IN Address;
Address.sin_family = PF_INET;
Address.sin_port = htons(1111);
Address.sin_addr.s_addr = INADDR_ANY;

bind(ServerSocket,(LPSOCKADDR)&Address, sizeof(Address));
listen(ServerSocket, 1);


for(;;)
{
ClientSocket = accept(ServerSocket, NULL, NULL);

isClientConnected = true;

string command;

Sleep(5);
command = Receive(ClientSocket);

cout << "Executing command...";
Send(ClientSocket,(char*)command.c_str());
}

Send(ClientSocket,"Closing Server...");
WSACleanup();
return 0;
}

int Send(SOCKET s, char *text)
{
return send(s, text,lstrlen(text),0);
}

char* Receive(SOCKET s)
{
char* buffer;
recv(s,buffer,sizeof(buffer),0);
return buffer;
}


client:


int main(int argn,char **argv)
{

SOCKET sock;
struct sockaddr_in sock_addr;
WSADATA data;

char command[1024];
char response[1024];
char mex[1024];

if(WSAStartup(MAKEWORD(2,0),&data) != 0)
{
closesocket(sock);
WSACleanup();
return 0;
}

sock=socket(PF_INET,SOCK_STREAM,0);
sock_addr.sin_family=PF_INET;
sock_addr.sin_port=htons(1111);
sock_addr.sin_addr.S_un.S_un_b.s_b1=127;
sock_addr.sin_addr.S_un.S_un_b.s_b2=0;
sock_addr.sin_addr.S_un.S_un_b.s_b3=0;
sock_addr.sin_addr.S_un.S_un_b.s_b4=1;

if(connect(sock,(struct sockaddr*)&sock_addr,sizeof(struct sockaddr)) != 0)
{
closesocket(sock);
WSACleanup();
return 0;
}

for (;;)
{
cout << "command: ";
cin >> command;
Send(sock,command);
cout << Receive(sock);
}

closesocket(sock);
WSACleanup();
return 0;
}

char* Receive(SOCKET s)
{
char* buffer;
recv(s,buffer,sizeof(buffer),0);
return buffer;
}


int Send(SOCKET s, char *text)
{
return send(s, text,lstrlen(text),0);
}



Vi prego corregete questa roba che ci sto sopra da un giorno!

<OT>
Domanda stupida: ma al server c++ potrei dialogare con un server in c# vero?
</OT>

aiutatemi ragazzi! I'm in your hands...

:ciauz:

MacApp
26-10-2007, 22:40
Originariamente inviato da MRj92
<OT>
Domanda stupida: ma al server c++ potrei dialogare con un server in c# vero?
</OT>

<OT>
Il protocollo TCP/IP indipendente dal linguaggio di programmazione o dal sistema operativo utilizzato.
</OT>

EDIT: riguardo al tuo problema... la domanda stupida la faccio io: hai aperto la porta 1111 del tuo firewall?

shodan
26-10-2007, 23:54
Originariamente inviato da MRj92


char* Receive(SOCKET s, int& charsRcv)
{
char* buffer = new char[QUANTO_MI_SERVE];
charsRcv = recv(s,buffer,QUANTO_MI_SERVE,0);
return buffer;
}


Il parametro di ritorno della recv importante visto che indica quanti bytes sono stati ricevuti nel caso tu voglia null terminare il buffer.

MRj92
27-10-2007, 08:28
EDIT: riguardo al tuo problema... la domanda stupida la faccio io: hai aperto la porta 1111 del tuo firewall?

si si a posto!



Originariamente inviato da MRj92
codice:

char* Receive(SOCKET s, int& charsRcv)
{
char* buffer = new char[QUANTO_MI_SERVE];
charsRcv = recv(s,buffer,QUANTO_MI_SERVE,0);
return buffer;
}



Il parametro di ritorno della recv importante visto che indica quanti bytes sono stati ricevuti nel caso tu voglia null terminare il buffer.

Idem! non cambia!

oregon
27-10-2007, 10:10
Allora ... per la parte server devi modificare la Receive in questo modo



char* Receive(SOCKET s)
{
char* buffer = new char[200];
int r=recv(s,buffer,200,0);
buffer[r]=0;
return buffer;
}


e nel WinMain devi fare le modifiche al ciclo (la accept deve stare fuori...)



ClientSocket = accept(ServerSocket, NULL, NULL);
isClientConnected = true;

for(;;)
{
string command;

Sleep(5);
command = Receive(ClientSocket);

string resp = "Executing command ... " + command;
Send(ClientSocket,(char*)resp.c_str());
}


Per quanto riguarda il client, anche in questo devi modificare la Receive



char* Receive(SOCKET s)
{
char* buffer = new char[200];
int r = recv(s,buffer,200,0);
buffer[r]=0;
return buffer;
}


e nel main aggiungi un newline in questa linea



cout << "\ncommand: ";


Mi sembra ovvio che tante altri punti sono da rivedere, ma e' evidente che si tratta di codice di studio ... (a proposito ... che tipo di codice stai studiando ... ? :D Ho qualche dubbio ...)

MRj92
27-10-2007, 14:39
grazie per l'aiuto! ora funziona.


Mi sembra ovvio che tante altri punti sono da rivedere, ma e' evidente che si tratta di codice di studio ...

Me li puoi indicare per cortesia?



(a proposito ... che tipo di codice stai studiando ... ? Ho qualche dubbio ...)

A preso codice da tanti programmi trovati in rete poich non sono riuscito a trovare una guida!
In msdn fanno tutti esempi lunghi e difficili!

oregon
27-10-2007, 15:29
Originariamente inviato da MRj92
grazie per l'aiuto! ora funziona.

Di nulla ...




Me li puoi indicare per cortesia?

Beh ... per esempio

1) hai dichiarato questi

char command[1024];
char response[1024];
char mex[1024];

ma non li usi ...

2) qui fai una closesocket

if(WSAStartup(MAKEWORD(2,0),&data) != 0)
{
closesocket(sock);
WSACleanup();
return 0;
}

ma il socket non e' ancora aperto ...

3) usi una for "infinita"

for(;;)

ma cosi' il server non puo' essere mai chiuso ...

4) se non usi dei thread, non potrai accettare connessioni da piu' client ma solamente dal primo ...

5) non controlli l'effettiva riuscita di alcune funzioni (listen, accept ...)

6) a cosa ti serve

isClientConnected = true;

se poi non lo usi?

Per quanto riguarda la mia ultima domanda, forse non sono stato chiaro ... come mai stai studiando/scrivendo questo tipo di programma ? A COSA ti serve ?

shodan
27-10-2007, 16:05
7) Non deallochi il buffer costruito nella Receive

MRj92
27-10-2007, 21:17
1) hai dichiarato questi

char command[1024];
char response[1024];
char mex[1024];

ma non li usi ...

2) qui fai una closesocket

if(WSAStartup(MAKEWORD(2,0),&data) != 0)
{
closesocket(sock);
WSACleanup();
return 0;
}

ma il socket non e' ancora aperto ...

Qui sono errori di copia incolla perch come ho detto prima ho attinto da pi fonti.
Questo codice il primo dei primi esempi per capire il funzionamento.



3) usi una for "infinita"

for(;;)

ma cosi' il server non puo' essere mai chiuso ...

Cosa consigli te? un while? e come uscire dal ciclo?




4) se non usi dei thread, non potrai accettare connessioni da piu' client ma solamente dal primo ...

si questo intenzionale.


5) non controlli l'effettiva riuscita di alcune funzioni (listen, accept ...)

era in programma ;)



6) a cosa ti serve

isClientConnected = true;

se poi non lo usi?

sempre errore di troppi cut&paste.


Per quanto riguarda la mia ultima domanda, forse non sono stato chiaro ... come mai stai studiando/scrivendo questo tipo di programma ? A COSA ti serve ?

Devo mettere in comunicazione i pc di casa (sopra e sotto) collegati tramite LAN per poter fare copie senza salire 1000 volte le scale! ;)

La pigrizia umana! :D

un po' mi da fastidio che mi credi un lameruccio :(


7) Non deallochi il buffer costruito nella Receive

ora correggo tutti gli errori.

Scusate, lo so che erano banalissimi errori ma ero fuso! :rollo: non so come non ho fatto a non acccorgemene!

Sono abituato con il c# e quindi con buffer e cose varie non ci entravo in conflitto da un po'...

oregon
27-10-2007, 21:27
Originariamente inviato da MRj92
Cosa consigli te? un while? e come uscire dal ciclo?

Intanto il server e' scritto senza "interfaccia" e l'unico modo di fermarlo e' tramite il Task Manager ...

Se inserisci un modo per controllarlo (magari da tastiera con il tasto ESC) potresti usare una while ...



Devo mettere in comunicazione i pc di casa (sopra e sotto) collegati tramite LAN per poter fare copie senza salire 1000 volte le scale! ;)

La pigrizia umana! :D

un po' mi da fastidio che mi credi un lameruccio :(

Due computer in LAN comunicano anche senza un programma del genere ... andiamo ... per copiare un file esistono tanti metodi standard che il sistema operativo mette a disposizione ... share, ftp ...

Per quanto riguarda "il lameruccio", non ho mai detto nulla del genere ... lo stai dicendo tu ... :)

Loading