PDA

View Full Version : Socket Win-Lin


Luc@s
17-05-2004, 18:34
#ifndef SOCK_HPP
#define SOCK_HPP

#ifdef WIN32
#include <winsock2.h>
typedef SOCKET sock_t;
#define CLOSE(x) closesocket(x); WSACleanup();
#define SEND(sck, msg) send(sck, msg, sizeof(msg), 0);
#define RECV(sck, msg) recv(sck, msg, sizeof(msg), 0);
#elif def LINUX
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
typedef int sock_t;
#define CLOSE(x) close(x);
#define SEND(sck, msg) write(sck,msg,strlen(msg))
#define RECV(sck, msg) read(sck,msg,strlen(msg))
#endif


#endif


Questo colma le leggeredifferenze tra win e lin riguardo ai socket??

Tnk

ilsensine
17-05-2004, 19:44
Sì e no.
Innanzitutto una nota cosmetica: nelle macro non aggiungere il ";" (altrimenti negli if...else sei fregato).
Per lo stesso motivo, se hai
#define a(x) b(x); c(x);
dovresti scrivere

#define a(x) do { \
b(x); \
c(x); } while(0)

Riguardo al codice, non usare WSACleanup quando chiudi il socket, in quanto potresti voler aprire più socket (WSAStartup va chiamata solo all'apertura del primo socket, e la cleanup solo alla chiusura dell'ultimo, o dell'applicazione).
Infine, usa anche nella versione linux le funzioni send e recv -- sono praticamente le stesse che su windows.

Luc@s
17-05-2004, 22:41
ecco il code finale:

#ifndef SOCK_HPP
#define SOCK_HPP

#include <iostream>
/// Safe Array deleting
#define ARRAY_SAFE_DELETE(ptr) delete[] ptr; ptr = NULL;

///
/// This is a generalization of socket
///
typedef int sock_t;
#ifdef __WIN__
//#warning "Win32 Mode On"
#include <winsock2.h>
#define CLOSE(x) closesocket(x);
#define SEND(sck, msg) send(sck, msg, sizeof(msg), 0)
#define RECV(sck, msg) recv(sck, msg, sizeof(msg), 0)
#elif defined(__LINUX__)
#warning "Linux Mode On"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define CLOSE(x) close(x);
#define SEND(sck, msg) write(sck,msg,strlen(msg))
#define RECV(sck, msg) read(sck,msg,strlen(msg))
#endif

/// The Error Enum
enum
{
ERR_SOCK_INVALID = 0x0, /// invalid socket
ERR_SOCK_CONNECT, /// error in connection
ERR_SOCK_SEND, /// error in send
ERR_SOCK_RECV, /// error in recv
};
///
/// Client Socket
///
class CClientSocket
{
private:
sock_t my_socket;
#ifdef __WIN__
WSAData wsaData;
#endif
struct hostent *host_entry;
struct sockaddr_in server;
public:
CClientSocket();
~CClientSocket();
int Build(const std::string addr, unsigned short port);
void Close();
int Read(char *buf);
int Write(char *buf);
};

CClientSocket::CClientSocket()
{
#ifdef __WIN__
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
}

CClientSocket::~CClientSocket()
{
}

int CClientSocket::Read(char *buf)
{
if(RECV(my_socket, buf) != 0)
return ERR_SOCK_RECV;
return 0;
}

int CClientSocket::Write(char *buf)
{
if(SEND(my_socket, buf) != 0)
return ERR_SOCK_SEND;
return 0;
}

int CClientSocket::Build(const std::string addr, unsigned short port)
{
my_socket = socket(AF_INET,SOCK_STREAM,0);

host_entry = gethostbyname(addr.c_str());

server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = *(unsigned long*) host_entry->h_addr;

if(connect(my_socket, (sockaddr*)&server, sizeof(server)) != 0)
return ERR_SOCK_CONNECT;
return 0;
}

void CClientSocket::Close()
{
CLOSE(my_socket)
}



#endif

ilsensine
17-05-2004, 22:44
A parte il fatto che hai ignorato metà dei miei suggerimenti ( :D ), ti INVITO, come ti ho già detto un'altra volta, a correggere questa CASTRONERIA:
#define RECV(sck, msg) recv(sck, msg, sizeof(msg), 0)
Mi ascolti, eh? :D

ilsensine
17-05-2004, 22:46
Anche queste sono castronerie ;)

if(RECV(my_socket, buf) != 0) return ERR_SOCK_RECV;

if(SEND(my_socket, buf) != 0) return ERR_SOCK_SEND;

ilsensine
17-05-2004, 22:49
Altre imprecisioni minori:

my_socket = socket(AF_INET,SOCK_STREAM,0);
Non controlli il valore di ritorno nel caso che la socket fallisca.

host_entry = gethostbyname(addr.c_str());
Se l'host non esiste/non è raggiungibile, la funzione ritorna NULL.
Attenzione se fai applicazioni multithread: la gethostbyname non è "reentrant" (almeno su linux; esiste la gethostbyname_r)

if(connect(my_socket, (sockaddr*)&server, sizeof(server)) != 0)
return ERR_SOCK_CONNECT;
Se la connect fallisce, chi libera il socket che hai allocato poche righe sopra?

Luc@s
18-05-2004, 07:08
tnk x i suggerimenti.
Ora li mettero in pratica :D