Hi,
Acabei de escrever uma classe bem simples para Sockets em C++ (Windows).
A classe pode trabalhar sob os protocolos UDP e TCP. Há as seguintes funções:
QuoteWinsock.Iniciar() -> inicia o uso do winsock;
Winsock.Terminar() -> finaliza o uso;
Socket.Criar(VALOR) = cria um socket. O parâmetro VALOR é um inteiro que pode ser 1 - TCP ou 2 - UDP;
Socket.Conectar(hostname,porta) -> se conecta a um computador remoto;
Socket.Aguardar(porta,num) -> aguarda um número "num" de conexões em uma porta "porta";
Socket.Aceitar(novo_socket) -> aceita uma conexão e a associa a uma nova classe de socket, se passado como NULL, a própria classe em uso é utilizada;
Socket.Enviar(dados) -> envia dados para um computador remoto;
Socket.Receber(tam) -> recebe um máximo "num" bytes e armazena os dados na variável "buffer" da classe.
Socket.HostRemoto() -> retorna o IP do computador remoto;
Socket.PortaRemota() -> retorna a porta utilizada no computador remoto;
Socket.Fechar() -> fecha o socket;
Bem, após uma breve explicação, vamos ao código:
#if !(defined _WINSOCK2_H || defined _WINSOCK_H)
#include <winsock2.h>
#endif
using namespace std;
string erro;
class WinSock{
private:
WSADATA wsa;
BOOL iniciado;
public:
void Iniciar();
void Terminar();
}WinSock;
class Socket
{
private:
SOCKET sock;
struct sockaddr_in addr;
struct hostent * host;
BOOL criado;
BOOL UDP;
public:
void Aceitar(Socket * novo_sock);
void Aguardar(DWORD porta, DWORD numero);
void Conectar(string hostname, DWORD porta);
void Criar(short tipo);
DWORD Enviar(string dados);
void Fechar();
string HostRemoto();
DWORD Receber(DWORD max);
DWORD PortaRemota();
string buffer;
};
/////////////////////////////////////////////////////////////////////////////////////////
void WinSock::Iniciar()
{
erro = "O Winsock ja foi inicializado!\n";
if(iniciado == 1)
throw erro;
erro = "Erro ao incializar o Winsock.\n";
if(WSAStartup(0x202,&wsa) == -1)
throw erro;
iniciado = 1;
}
/////////////////////////////////////////////////////////////////////////////////////////
void WinSock::Terminar()
{
erro = "Falha ao finalizar o uso do WinSock.\n";
if(WSACleanup() == -1)
throw erro;
iniciado = 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
void Socket::Criar(short tipo){
UDP = FALSE;
erro = "O socket ja foi criado!\n";
if(criado == 1)
throw erro;
short valores[2] = {SOCK_STREAM,SOCK_DGRAM};
erro = "Erro ao criar socket. O 'tipo' definido nao e' valido!\n";
if(tipo != 1 && tipo != 2)
throw erro;
erro = "Ocorreu um erro ao criar o socket.\n";
if((sock = socket(AF_INET,valores[tipo-1],0)) == -1)
throw erro;
if(tipo == 2)
UDP = TRUE;
criado = 1;
}
/////////////////////////////////////////////////////////////////////////////////////////
void Socket::Conectar(string hostname,DWORD porta)
{
erro = "Erro ao resolver o host: "" + hostname + "".\n";
if(!(host = gethostbyname(hostname.c_str())))
throw erro;
addr.sin_family = AF_INET;
addr.sin_port = htons(porta);
addr.sin_addr = *(struct in_addr*)host->h_addr;
erro = "Erro ao se conectar ao host "" + hostname + "".\n";
if(connect(sock,(struct sockaddr*)&addr,sizeof(addr)) == -1)
throw erro;
}
/////////////////////////////////////////////////////////////////////////////////////////
void Socket::Aguardar(DWORD porta, DWORD numero)
{
addr.sin_family = AF_INET;
addr.sin_port = htons(porta);
addr.sin_addr.s_addr = INADDR_ANY;
erro = "Erro ao configurar localmente o socket.\n";
if(bind(sock,(struct sockaddr*)&addr,sizeof(addr)) == -1)
throw erro;
if(UDP)
return;
erro = "Erro ao colocar o socket em modo de espera.\n";
if(listen(sock,numero) == -1)
throw erro;
}
/////////////////////////////////////////////////////////////////////////////////////////
void Socket::Aceitar(Socket * novo_sock)
{
if(UDP)
return;
int size_addr = sizeof(struct sockaddr_in);
int ret;
if(novo_sock == NULL)
ret = sock = accept(sock,(struct sockaddr*)&addr,&size_addr);
else
ret = novo_sock->sock = accept(sock,(struct sockaddr*)&novo_sock->addr,&size_addr);
erro = "Erro ao aceitar uma conexao pendente.\n";
if(ret == -1)
throw erro;
}
/////////////////////////////////////////////////////////////////////////////////////////
DWORD Socket::Enviar(string dados)
{
erro = "Erro ao enviar dados.\n";
DWORD ret;
if(!UDP)
ret = send(sock,dados.c_str(),dados.size(),0);
else
ret = sendto(sock,dados.c_str(),dados.size(),0,(struct sockaddr*)&addr,sizeof(addr));
if(ret == -1)
throw erro;
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////
DWORD Socket::Receber(DWORD MAX)
{
char buf[MAX];
DWORD ret;
int size_addr = sizeof(struct sockaddr_in);
if(!UDP)
ret = recv(sock,buf,MAX,0);
else
ret = recvfrom(sock,buf,MAX,0,(struct sockaddr*)&addr,&size_addr);
buf[ret-1] = '\0';
erro = "Erro ao receber dados.\n";
if(ret == -1)
throw erro;
buffer = "";
if(ret)
buffer = buf;
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////
string Socket::HostRemoto()
{
string ret;
ret = inet_ntoa(addr.sin_addr);
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////
DWORD Socket::PortaRemota()
{
return (DWORD)htons(addr.sin_port);
}
/////////////////////////////////////////////////////////////////////////////////////////
void Socket::Fechar()
{
closesocket(sock);
criado = 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
Códigos de exemplos:
http://three.fsphost.com/darkside/exemplos_socket.zip (http://three.fsphost.com/darkside/exemplos_socket.zip)
Bye xD
beleza dark side
vc voltou na ativa ?
rog
Mto bom ^^
Em breve pretendo iniciar em C++ e seus tutos já estão guardados hehe..
[]s
Dark_Side,
Muito bom, pois a maneira que vc cita antes os elementos fundamentais do codigo , facilita muito a compreesão do codigo...
Como o whit3_sh4rk, estou começando em c e seues tutoriais estão ajudando muito na otimização de meus programas...
Sem +...