Pessoal fiz um chat bem humilde com sockets, que funciona em linux e windows, e com instruções para compilar no dev e no codeblocks.
Estou postando aqui porque é muito difícil achar na net uns exemplos bacanas e comentados.
*Obs: Os comentários explicativos das ações das funções foi baseado em um livro.
------------------------------------------------------------------------------
Servidor: servidor.cpp
/*
Intruções de Compilação:
DevC++: Tools > Compiler Options > Add linker -lws2_32.
Codeblocks: Menu Settings > Compiler and Debugger > Linker Settings > Other Linker Options > -lws2_32.
------------------------------------------------------------------------------------------------------------
Dependências:
windows -> winsock2.h, WSDATA wsa_data.
unix/linux -> <sys/types.h>, <sys/socket.h>, <arpa/inet.h>.
comuns -> <iostream>, <unistd.h>, <string.h>
*/
#include <iostream>
#include <unistd.h>
#include <string.h>
#ifdef unix
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
WSADATA wsa_data;
#endif
#define TAMANHO_MESG 501
int main(){
//Variável para receber conexão.
int conexao = -1;
//Variável para receber e enviar mensagem
char mensagem[TAMANHO_MESG];
//Variável para guardar o tamanho da mensagem recebida
int tam_mesg_receb=0;
//Declarando estrutura Servidor e Cliente
struct sockaddr_in servidor;
struct sockaddr_in cliente;
#ifndef unix
//Startando sockets
WSAStartup(MAKEWORD(2, 0), &wsa_data);
//Tamanho do estrutura sockaddr_in
int tamanho = sizeof(struct sockaddr_in);
#else
//Tamanho do estrutura sockaddr_in
socklen_t tamanho = sizeof(struct sockaddr_in);
#endif
/*
Criando Socket.
função socket(int domain,int type,int protocol);
domain: domínio específico. Ex: AF_INET -> suporta UPD,TCP, etc.
type: tipo definido. Ex: SOCK_STREAM -> scoket de fluxo.
protocol: protocolo definido. Ex: IPPROTO_TCP -> suporta TCP, IPPROTO_UDP -> UDP, 0 -> protocolo padrão.
*/
int meusocket = socket(AF_INET,SOCK_STREAM,0);
/*
Definindo endereçamento do Servidor
sin_family: familia do scoket. Ex: AF_INET -> UDP, TCP, etc.
sin_addr.s_addr: ip do servidor. Ex: INADDR_ANY -> declara como 0.0.0.0 para funcionar com qualquer ip disponível.
sin_port: porta de escuta. Ex: htons(80)-> htons transforma a porta 80 em digitos específicos para redes.
*/
servidor.sin_family = AF_INET;
servidor.sin_addr.s_addr = htonl(INADDR_ANY);
servidor.sin_port = htons(8767);
//Completando a estrutura socktaddr_in com valores nulo para que fique do tamanho igual ao da sockaddr padrão
memset(&(servidor.sin_zero),'\0', sizeof(servidor.sin_zero));
/*
Comunicando o Socket com endereço de rede.
função bind(int s, const struct sockaddr *name, int namelen);
s: meusocket ou variável que foi criada recebendo o retorno da função scoket().
*name: apontador para estrutura padrão do AF_INET(family).
name_len: tamanho da estrutura.
*/
bind(meusocket, (struct sockaddr *)&servidor, sizeof(struct sockaddr));
/*
Preprando para receber conexões
função listen(int s, int backlog);
s: meusocket ou variável que foi criada recebendo o retorno da função scoket().
backlog: limite máximo de clientes para conectar.
*/
listen(meusocket,1);
std::cout << "Aguardando Conexao ... \n";
//Verificando se há conexões
while(1){
/*
Criando socket a partir de conexões pendentes
função accept(int s, struct sockaddr *addr, socklen_t *addrlen);
s: meusocket ou variável que foi criada recebendo o retorno da função scoket().
*addr: apontador para estrutura padrão do AF_INET (family).
*addrlen: tamanho da estrutura.
*/
conexao = accept(meusocket, (struct sockaddr *)&cliente, &tamanho);
//Avisando sobre a conexão estabelecida com um ip
std::cout << "Conexão Estabelecida com o ip: " << inet_ntoa(cliente.sin_addr) << "\n";
//Comunicando com cliente
do{
//Solicitando dados de envio e finalizando vetor
std::cout << "\nDigite uma mensagem ou (0) - para sair:";
fgets(mensagem, TAMANHO_MESG, stdin);
mensagem[TAMANHO_MESG] = '\0';
//verificando se a mensagem vai ser enviada
if(mensagem[0] != '0'){
/*
Transmitindo Pacotes
função send(int c, const void *msg, size_t len, int flags);
c: conexão ou variável que foi criada recebendo o retorno da função accept().
*msg: mensagem a ser enviada.
len: tamanho da mensagem a ser enviada.
flag: tipos de comportamento no envio da mensagem. Ex: 0 -> padrão.
*/
send(conexao, mensagem, TAMANHO_MESG, 0);
//aguardando resposta
do{
/*
Recebendo pacotes
função recv(int s, void *buf, size_t len, int flags);
s: meusocket ou variável que foi criada recebendo o retorno da função scoket().
*buf: mensagem recebida
*len: tamanho máximo para receber mensagem.
flag: tipos de comportamento no envio da mensagem. Ex: 0 -> padrão.
*/
tam_mesg_receb = recv(conexao, mensagem, TAMANHO_MESG, 0);
//verificando se houve mensagem recebida
if(tam_mesg_receb > 0){
//finalizando mensagem
mensagem[tam_mesg_receb] = '\0';
//imprimindo mensagem
if(mensagem[0] != '0')
std::cout << "\nCliente diz: " << mensagem;
}//fim if()
}while(tam_mesg_receb <= 0);//fim do{}
}//fim if()
}while(mensagem[0] != '0');//fim do{}
/*
Terminando conexão
função close(int c);
c: conexão ou variável que foi criada recebendo o retorno da função accept().
*/
close(conexao);
std::cout << "\nConexao Finalizada";
} //fim while()
/*
Terminando socket
função close(int s);
s: meusocket ou variável que foi criada recebendo o retorno da função scoket().
*/
close(meusocket);
//retorno main()
return 0;
}//fim main()
------------------------------------------------------------------------------
Cliente: cliente.cpp
/*
Intruções de Compilação:
DevC++: Tools > Compiler Options > Add linker -lws2_32.
Codeblocks: Settings > Compiler and Debugger > Linker Settings > Other Linker Options > -lws2_32.
------------------------------------------------------------------------------------------------------------
Dependências:
windows -> winsock2.h, WSDATA wsa_data.
unix/linux -> <sys/types.h>, <sys/socket.h>, <arpa/inet.h>.
comuns -> <iostream>, <unistd.h>, <string.h>
*/
#include <iostream>
#include <unistd.h>
#include <string.h>
#ifdef unix
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
WSADATA wsa_data;
#endif
#define TAMANHO_MESG 501
int main(){
//Variável para receber conexão.
int conexao = -1;
//Variável para receber e enviar mensagem
char mensagem[TAMANHO_MESG];
//Variável para guardar o tamanho da mensagem recebida
int tam_mesg_receb=0;
//Declarando estrutura Servidor
struct sockaddr_in servidor;
#ifndef unix
//Startando sockets
WSAStartup(MAKEWORD(2, 0), &wsa_data);
#endif
/*
Criando Socket.
função socket(int domain,int type,int protocol);
domain: domínio específico. Ex: AF_INET -> suporta UPD,TCP, etc.
type: tipo definido. Ex: SOCK_STREAM -> scoket de fluxo.
protocol: protocolo definido. Ex: IPPROTO_TCP -> suporta TCP, IPPROTO_UDP -> UDP, 0 -> protocolo padrão.
*/
int meusocket = socket(AF_INET,SOCK_STREAM,0);
/*
Definindo endereçamento do Servidor
sin_family: familia do scoket. Ex: AF_INET -> UDP, TCP, etc.
sin_addr.s_addr: ip do servidor. Ex: 192.168.1.61 -> Ip do servidor.
sin_port: porta de escuta. Ex: htons(80)-> htons transforma a porta 80 em digitos específicos para redes.
*/
servidor.sin_family = AF_INET;
servidor.sin_addr.s_addr = inet_addr("189.13.133.30");
servidor.sin_port = htons(8767);
//Completando a estrutura socktaddr_in com valores nulo para que fique do tamanho igual ao da sockaddr padrão
memset(&(servidor.sin_zero),'\0', sizeof(servidor.sin_zero));
/*
Conectando ao servidor
função connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
s: meusocket ou variável que foi criada recebendo o retorno da função scoket().
*serv_addr: apontador para servidor.
addrlen: tamanho do endereço do servidor
*/
conexao = connect(meusocket, (struct sockaddr *)&servidor,sizeof(struct sockaddr));
std::cout << "\nConectando ao servidor: " << inet_ntoa(servidor.sin_addr) << "\n";
//comunicando com servidor
do{
/*
Recebendo pacotes
função recv(int s, void *buf, size_t len, int flags);
s: meusocket ou variável que foi criada recebendo o retorno da função scoket().
*buf: mensagem recebida
*len: tamanho máximo para receber mensagem.
flag: tipos de comportamento no envio da mensagem. Ex: 0 -> padrão.
*/
tam_mesg_receb = recv(meusocket, mensagem, TAMANHO_MESG, 0);
//verificando se houve mensagem recebida
if(tam_mesg_receb > 0 && mensagem[0] != '0'){
//finalizando mensagem
mensagem[tam_mesg_receb] = '\0';
//imprimindo mensagem
std::cout << "\nServidor diz: " << mensagem;
//Solicitando dados de envio e finalizando vetor
std::cout << "\nDigite uma mensagem ou (0) - para sair:";
fgets(mensagem, TAMANHO_MESG, stdin);
mensagem[TAMANHO_MESG] = '\0';
//verificando se a mensagem vai ser enviada
if(mensagem[0] != '0'){
/*
Transmitindo Pacotes
função send(int c, const void *msg, size_t len, int flags);
c: conexão ou variável que foi criada recebendo o retorno da função connect().
*msg: mensagem a ser enviada.
len: tamanho da mensagem a ser enviada.
flag: tipos de comportamento no envio da mensagem. Ex: 0 -> padrão.
*/
send(meusocket, mensagem, TAMANHO_MESG, 0);
tam_mesg_receb = 0;
}//fim if()
}//fim if()
}while(mensagem[0] != '0' && tam_mesg_receb == 0);//fim do{}
/*
Terminando conexão
função close(int c);
c: conexão ou variável que foi criada recebendo o retorno da função accept().
*/
close(conexao);
std::cout << "\nConexao Finalizada";
/*
Terminando socket
função close(int s);
s: meusocket ou variável que foi criada recebendo o retorno da função scoket().
*/
close(meusocket);
//retorno main()
return 0;
}//fim main()
------------------------------------------------------------------------------