PDA

View Full Version : [C++]Sock


Luc@s
01-05-2004, 20:03
Ho cercato di farmi una lib socket per Lin-Win e questo il risultato:

/// The Os inclusion
#ifdef WINDOWS
#include <Winsock2.h>
#include <windows.h>
#elif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif

#include <string>

class WinClientSock
{
std::string addr;
#ifdef WINDOWS
SOCKET sock_fd; /// the win socket
#elif
int sock_fd; /// the lin socket
#endif
struct sockaddr_in temp; /// the sockaddr structure
struct hostent *h; /// the host structure
int port;
public:
WinClientSock();
WinClientSock(const std::string addr, int port);
~WinClientSock();
int Open();
void Exit();
const char *getHost()
{
return addr.c_str();
};
const int getPort()
{
return port;
};
int Receve(char *buf);
int Send(char * buff);
};

WinClientSock::WinClientSock()
{
addr = "localhost";
/// defining port
#ifdef DEF_PORT
port = 6000;
#elifdef DEF_PORT
port = DEF_PORT;
#endif
}

WinClientSock::WinClientSock(const std::string addr, int port)
{
this->port = port;
this->addr = addr;
}

WinClientSock::~WinClientSock()
{
Exit();
}

int WinClientSock::Open()
{
int ret;
#ifdef WINDOWS
WSADATA wsaData;
WORD version;
int error;

version = MAKEWORD( 2, 0 );
error = WSAStartup( version, &wsaData );

/* check for error */
if ( error != 0 )
{
return -1;
}

/* check for correct version */
if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 )
{
WSACleanup();
return -1;
}

sock_fd = socket( AF_INET, SOCK_STREAM, 0 );

h = gethostbyname(addr.c_str());

temp.sin_family = AF_INET;
temp.sin_addr.s_addr = ((struct in_addr *)(h->h_addr))->s_addr;
temp.sin_port = htons(port);

if ( connect( sock_fd, (sockaddr*)&temp, sizeof(temp) ) == SOCKET_ERROR )
{
/* could not connect to server */
ret = -1;
}
else
{
ret = sock_fd;
}

#elif
temp.sin_family = AF_INET;
temp.sin_port = htons(PORT);

h = gethostbyname(addr.c_str());

if (0 == h) return -1;

bcopy(h->h_addr,&temp.sin_addr,h->h_length);

sock_fd = socket(AF_INET,SOCK_STREAM,0);

errore = connect(sock_fd,(struct sockaddr*) &temp, sizeof(temp));

if(errore == 0)
{
ret = sock_fd;
}
else
{
ret = -1;
}
#endif
return ret;
}

void WinClientSock::Exit()
{
#ifdef WINDOWS
closesocket(sock_fd);
WSACleanup();
#elif
close(sock_fd);
#endif
}

int WinClientSock::Receve(char *buf)
{
if(recv(sock_fd, buf, strlen(buf), 0 ) == 0)
{
return -1;
}
}

int WinClientSock::Send(char *buf)
{
if(send(sock_fd, buf, strlen(buf), 0 ) == 0)
{
return -1;
}
}


Il problema è che provandola:

#include <iostream>
#include <cstring>
#include "WinSockClient.hpp"

using namespace std;

int main(int argc, char *argv[])
{
WinClientSock sk("http://www.ngi.it", 23);
SOCKET client = (SOCKET) sk.Open();
if(-1 != client)
{
cout << "Open Ok \n";

char * buffer = new char[32];

/*
if(sk.Receve(buffer) == -1)
{
cout << "Error in recv\n";
}
else
{
cout << buffer;
}
*/

if(sk.Send(buffer) == -1)
{
cout << "Error in send\n";
}
else
{
cout << "Ok\n";
}

delete[] buffer;
}
char c;
cin >> c;
return 0;
}


Mi da errore di memoria che doveva essere read :(

Why???

Tnk 10000000000000

Luc@s
01-05-2004, 20:55
ho semi risolto, ora pero mi da connection ok ma nientaltro su linux e niente di niente su win:

/// The Os inclusion
#ifdef WINDOWS
#include <Winsock2.h>
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif

#include <string>

class WinClientSock
{
std::string addr;
#ifdef WINDOWS
SOCKET sock_fd; /// the win socket
#else
int sock_fd; /// the lin socket
#endif
struct sockaddr_in temp; /// the sockaddr structure
struct hostent *h; /// the host structure
int port;
public:
WinClientSock(int port);
WinClientSock(const std::string addr, int port);
~WinClientSock();
int Open();
void Exit();
const char *getHost()
{
return addr.c_str();
};
const int getPort()
{
return port;
};
int Receve(char *buf);
int Send(char * buff);
};

WinClientSock::WinClientSock(int port)
{
this->port = port;
}

WinClientSock::WinClientSock(const std::string addr, int port)
{
this->port = port;
this->addr = addr;
}

WinClientSock::~WinClientSock()
{
Exit();
}

int WinClientSock::Open()
{
int ret;
#ifdef WINDOWS
WSADATA wsaData;
WORD version;
int error;

version = MAKEWORD( 2, 0 );
error = WSAStartup( version, &wsaData );

/* check for error */
if ( error != 0 )
{
return -1;
}

/* check for correct version */
if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 )
{
WSACleanup();
return -1;
}

sock_fd = socket( AF_INET, SOCK_STREAM, 0 );

h = gethostbyname(addr.c_str());

temp.sin_family = AF_INET;
temp.sin_addr.s_addr = ((struct in_addr *)(h->h_addr))->s_addr;
temp.sin_port = htons(port);

if ( connect( sock_fd, (sockaddr*)&temp, sizeof(temp) ) == SOCKET_ERROR )
{
/* could not connect to server */
ret = -1;
}
else
{
ret = sock_fd;
}

#else
temp.sin_family = AF_INET;
temp.sin_port = htons(port);

h = gethostbyname(addr.c_str());

if (0 == h) return -1;

bcopy(h->h_addr,&temp.sin_addr,h->h_length);

sock_fd = socket(AF_INET,SOCK_STREAM,0);

int errore = connect(sock_fd,(struct sockaddr*) &temp, sizeof(temp));

if(errore == 0)
{
ret = sock_fd;
}
else
{
ret = -1;
}
#endif
return ret;
}

void WinClientSock::Exit()
{
#ifdef WINDOWS
closesocket(sock_fd);
WSACleanup();
#else
///close(sock_fd);
#endif
}

int WinClientSock::Receve(char *buf)
{
if(recv(sock_fd, buf, strlen(buf), 0 ) == 0)
{
return -1;
}
}

int WinClientSock::Send(char *buf)
{
if(send(sock_fd, buf, strlen(buf), 0 ) == 0)
{
return -1;
}
}

ilsensine
02-05-2004, 10:57
IMHO il tuo codice necessita di una certa revisione. Innanzitutto, visto che le funzioni socket POSIX di windows sono molto simili a quelle su linux, dovresti cercare di accorpare più codice possibile. Inoltre fai attenzione che (l'ho verificato in passato) la gethostbyname FALLISCE su win32 se passi un valido indirizzo IP al posto di un nome (inoltre, ti sei scordato la verifica h==NULL nella verisone win32). Sperabilmente, gli ultimi windows non hanno questa "feature".
Alcune cose qua e là:


version = MAKEWORD( 2, 0 );

Anche versioni precedenti di winsock funzionano

#ifdef WINDOWS
closesocket(sock_fd);
WSACleanup();
#else
///close(sock_fd);
#endif
}

La close nella versione linux va bene. Per semplificate il codice, usa la sola closesocket e, per linux, definisci
#define closesocket(x) close(x)
La WSACleanup è scorretta così come l'hai scritta: potresti aver aperto più socket!!


int WinClientSock::Send(char *buf)
{
if(send(sock_fd, buf, strlen(buf), 0 ) == 0)
{
return -1;
}
}

...se volessi inviare qualcosa che non è una stringa?
Nota che la send può fallire con valore <0!


int WinClientSock::Receve(char *buf)
{
if(recv(sock_fd, buf, strlen(buf), 0 ) == 0)
{
return -1;
}
}

Ma per favore! :D

Luc@s
03-05-2004, 13:37
ho risolto usando la lib in allegato :P

ilsensine
03-05-2004, 14:04
Originariamente inviato da Luc@s
ho risolto usando la lib in allegato :P
Stai scherzando, vero? :D Non avrai intenzione di usare quella roba? :D
Mi sembra più un esempio che una libreria utilizzabile ;)

Luc@s
03-05-2004, 14:09
Originariamente inviato da ilsensine
Stai scherzando, vero? :D Non avrai intenzione di usare quella roba? :D
Mi sembra più un esempio che una libreria utilizzabile ;)

per i miei scopi attuali..............mi va bene :D
Intanto ho imparato un po di + di quello che sapevo.
Poi se mi servira la migliorero :D

ilsensine
03-05-2004, 14:11
Migliorarla? Intendi "la _scriverò_" :D

Non inalare quella roba, fa male ;)

Luc@s
03-05-2004, 14:16
Originariamente inviato da ilsensine
Migliorarla? Intendi "la _scriverò_" :D


Ovviamente :D