PDA

View Full Version : [C\C++]Chat C++


4ndr34s
20-11-2009, 21:30
Salve a tutti, ho una chat scritta in c++ vorrei sapere come è possibile prendere l'ip della persona che invia il messaggio al server?
Questo è il codice:
Server:
#include <vector>
#include <ctime>
#include "Socket.h"

using namespace std;

struct mClient { SOCKET socket; string nick; };

DWORD WINAPI AcceptConnection(LPVOID Parameter);
DWORD WINAPI Receive(LPVOID Parameter);

void StartListenClient(Socket *s);
bool _Receive(mClient* c);
void SendToAll(const char* message);
void SendOne(const char* message,SOCKET s);
bool ExistNick(string nick);

vector<SOCKET>::iterator retpos(SOCKET s);
vector<string>::iterator _retpos(string s);
vector<SOCKET> CLIENT;
vector<string> NICK;


int main()
{
try {
SetConsoleTitle("cChat - Server");
DWORD mThread;
string ip="127.0.0.1";
cout<<"Inizializzazione in corso...\n";
Socket* server= new Socket(ip,8585);
server->Bind();
server->Listen(10);
cout<<"Inizializzazione completata!\n"
<<"Server pronto a ricevere connessioni sulla porta 8585.\n"
<<"==> Scrivere ::quit per stoppare il server <==\n"
<<"======================================================\n";

CreateThread(NULL,0,AcceptConnection,server,0,&mThread);
string a,send="";
while(a!="::quit\n") {
getline(cin,a,'\n');
a+="\n";
send = "::server:: "+a;
SendToAll(send.c_str());
fflush(stdin);
}
}catch(SocketException s) {
cout<<s.ErrorMessage();
}
return 0;
}

DWORD WINAPI AcceptConnection(LPVOID Parameter) {
Socket *s=(Socket*)Parameter;
while(1)
StartListenClient(s);
return 0;
}

void StartListenClient(Socket *s) {
DWORD mThread;
SOCKET ss;
string nick="Banned User";
ss=s->Accept();
if(ss!=INVALID_SOCKET) {
CLIENT.push_back(ss);
NICK.push_back(nick);
mClient *c = new mClient;
c->socket=ss;
c->nick=nick;

CreateThread(NULL,0,Receive,(void*)c,0,&mThread);
cout<<"Client connesso!\n";
}
}

DWORD WINAPI Receive(LPVOID Parameter) {
mClient *c=(mClient*)Parameter;
while(1)
if(_Receive(c)) break;
return 0;
}

bool _Receive(mClient* c) {
string value="";
char buff[4096]="";
char timebuff[9]="";
int ret=0;
ret = recv(c->socket,buff,sizeof(buff)+1,0);
if(ret!=-1) {
value+="[";
value+=_strtime(timebuff);
value+="] ";
value+="<";
value+=c->nick;
value+="> ";
value+=buff;
value+='\n';
cout<<value;
cout<<"\n"<<buff;
SendToAll(value.c_str());
return 0;
}else {
CLIENT.erase(retpos(c->socket));
NICK.erase(_retpos(c->nick));
return 1;
}
}

void SendToAll(const char* message) {
vector<SOCKET>::iterator i;
vector<string>::iterator j;
for(i=CLIENT.begin(),j=NICK.begin();i!=CLIENT.end();i++,j++) {
if(send(*i,message,strlen(message)+1,0) == -1) {
CLIENT.erase(i);
NICK.erase(j);
}
}

}

void SendOne(const char* message,SOCKET s) {
send(s,message,strlen(message)+1,0);
}

bool ExistNick(string nick) {
vector<string>::iterator it;
for(it=NICK.begin();it!=NICK.end();it++)
if(*it == nick) return true;
return false;
}

vector<SOCKET>::iterator retpos(SOCKET s) {
vector<SOCKET>::iterator it;
for(it=CLIENT.begin();it!=CLIENT.end();it++)
if(*it == s) break;

return it;
}

vector<string>::iterator _retpos(string s) {
vector<string>::iterator it;
for(it=NICK.begin();it!=NICK.end();it++)
if(*it == s) break;

return it;
}

Client:
#include "Socket.h"

using namespace std;

DWORD WINAPI Receive(LPVOID Parameter);

int main()
{
try {
SetConsoleTitle("cChat - Client");
DWORD mThread;
string address="127.0.0.1";
//cout<<"Inserisci l'indirizzo del server: ";
Socket *s=new Socket(address,8585);
s->Connect();
cout<<"\nConnessione al server effettuata !"
<<"\n===> Scrivi ::quit per uscire <===\n"
<<"=====================================\n\n";
CreateThread(NULL,0,Receive,s,0,&mThread);
string a="Ban me I'm hacking";
//cout<<"Inserisci il nick: ";
//getline(cin,a,'\n');
//s->Send(a,a.length());
s->Send(a,a.length());
/*while(a!="::quit") {
//getline(cin,a,'\n');
if(a!="::quit")
if(s->Send(a,a.length())==-1) {
cout<<"Connessione al server caduta!"<<endl;
break;
}
}*/
}catch(SocketException e) {
cout<<e.ErrorMessage()<<endl;
}
return 0;
}

DWORD WINAPI Receive(LPVOID Parameter) {
Socket *s=(Socket*)Parameter;
string p="";
while(1) {
if(s->Receive(p)!=-1) {
cout<<p;
p.clear();
}else break;
}
return 0;
}

tomminno
20-11-2009, 21:48
Supponendo che tu stia usando i socket bsd c'è la funzione getpeername.

Ah un consiglio sulle eccezioni usa i riferimenti, meglio ancora un const reference.

fero86
20-11-2009, 21:48
http://www.linuxmanpages.com/man2/getpeername.2.php
http://www.linuxmanpages.com/man2/getsockname.2.php

4ndr34s
21-11-2009, 05:52
Sapreste dirmi come e dove la dovrei collolare nel codice?
non tanto mi è chiaro come funziona.

tomminno
21-11-2009, 12:07
Sapreste dirmi come e dove la dovrei collolare nel codice?
non tanto mi è chiaro come funziona.

Dove collocarla dipende anche dal punto in cui vuoi consocere i dati, potresti anche pensare di aggiugnerla alla classe Socket.
Per il funzionamento richiede in ingresso il descrittore del socket (che nel tuo caso mi sembra essere la varibile socket della classe Socket), il puntatore a una struttura sockaddr_in e il puntatore alla dimensione di sockaddr_in, in uscita ti troverai i dati dell'ip e della porta del socket remoto.

4ndr34s
21-11-2009, 14:06
io vorrei collocarla nel lato server, dove riceve il messaggio :
bool _Receive(mClient* c) {
string value="";
char buff[4096]="";
char timebuff[9]="";
int ret=0;
ret = recv(c->socket,buff,sizeof(buff)+1,0);
if(ret!=-1) {
value+="[";
value+=_strtime(timebuff);
value+="] ";
value+="<";
value+=c->nick;
value+="> ";
value+=buff;
value+='\n';
cout<<value;
cout<<"\n"<<ip QUi!;
SendToAll(value.c_str());
return 0;
}else {
CLIENT.erase(retpos(c->socket));
NICK.erase(_retpos(c->nick));
return 1;
}
}

tomminno
21-11-2009, 20:53
Io aggiungerei un elemento alla struct mClient da valorizzare dopo l'Accept per evitare di calcolare tutte le volte l'informazione.

4ndr34s
21-11-2009, 21:44
Edit4: ok ora funziona alla grande, grazie miller per l'aiuto datomi.
Unico Problema: non riesco a linkare le librerie in VC++ 6 come faccio?
dovrei linkare questa libreria libws2_32.a ma ho notato che non è neanche presente nella cartelle delle librerie del visual c, come faccio?

tomminno
22-11-2009, 13:49
Edit4: ok ora funziona alla grande, grazie miller per l'aiuto datomi.
Unico Problema: non riesco a linkare le librerie in VC++ 6 come faccio?
dovrei linkare questa libreria libws2_32.a ma ho notato che non è neanche presente nella cartelle delle librerie del visual c, come faccio?

Io direi che devi linkare ws2_32.lib

Scusa ma perchè stai usando un compilatore di 11 anni fa?
Usa VisualStudio 2008 Express che è un altro mondo (meglio ancora VS2010 Beta2).

4ndr34s
22-11-2009, 14:58
Quanto sono fesso xD
certe volte....
io avevo copiato e incollato il codice in visual c ma non avevo aggiunto i file del progetto di code block nel progetto del visual e quindi dava tutti quei errori xD
grazie mille per l'aiuto