sexta-feira, julho 17, 2009

Socket em *NIX

Tirei esse do fundo do báu, os dos HD's se prefirir e datado de 05/2005 e eu fiz pro grupo União Atlantica, e um código comentado que serve como tutorial, ele mostra como estabelecer conexão cliente-servidor usando sockets em *NIX creio que não funcione no windows.

****Cliente***



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

int main(int argc,char *argv[])
{
int TSocket;
struct sockaddr_in servidor;
char msg[17] = "Uniao Atlantica\0";
//inicia o socket
//nota parametro 1 tipo familia do socke
//pode ser AF_INET (ARPA INTERNET PROTOCOLOS) "mais usada"
//"" AF_UNIX (UNIX INTERNET PROTOCOLOS)
//"" AF_ISO (ISO PROTOCOLOS)
//"" AF_NS (XEROX NETWORK SYSTEM PROTOCOLOS)

//nota parametro tipos SOCK_STREAM = TCP, SOCK_DGRAM = UDP
//terceiro parametro 0 (faleremos depois)
TSocket = socket(AF_INET,SOCK_STREAM,0);

if (TSocket < 0) //simples checagem de erro
{
printf("Erro\n");
exit(0);
}

//montando a estrutu servidor essa estrutura mas TSocket vao fazer a conecao
//entre o nosso cliente e o servidor

//estrutura sockaddr_in
//struct sockaddr_in {
//short int sin_family; { do endreco (ex: AF_INET)}
//unsignet short int sin_port; (numero da porta)
//struct sin_addr in_addr; (ip do host)
//unsignet char sin_zero[8]; (zera a estrutura)
//}

servidor.sin_family = AF_INET;
servidor.sin_port = htons(3506); //porta que vamos usar
//o htons significa host to network short
//mais info (man pages)
servidor.sin_addr.s_addr = inet_addr("127.0.0.1"); //ip destino
bzero(&(servidor.sin_zero),8); //zera o resto da estrutura

//agora a funcao connect essa funcao faz a conecao com o servidor
if (connect(TSocket,(struct sockaddr *)&servidor,sizeof(servidor)) < 0)
{
printf("erro ao fazer a conexao\n");
exit(0);
}

//agora vamos usar vamos enviar uma mesnsagem para o servidor
//usnado a funcao send();
//prototipo
//int send(int TSocket,const void *msg,int size_t len,int flags)

send(TSocket,&msg,sizeof(msg),0);

//agora fechamos nosso cliente
close(TSocket);
//bom Daniel pela experiencia que voce tem com redes acho q deu pra entender tudo ate agora
//vc manja mais de ingles que eu e esse seu debian ta lotado de man pages
//qualquer coisa psota sua msg pro grupo ou pra min que a gente resolve
//pra compilar gcc cliente.c -o cliente
//executar ./cliente
return 0;
}

****Servidor.c****


//o que tem de novo aki e sao a funcoes bind() e listen()
//a funcao bind associa um socket ao nosso servidor local (eu numca entendi isso direita mas fazer o que)
//a funcao listem faz nosso servidor esperar uma conecao faz ele escutar
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>

int main(int argc,char *argv[])
{
int TSocket,Clientes[5],tamanho;
struct sockaddr_in local,cliente[5];
int Count,Next =0;
char *recived_msg; //cinco strings para evitar que um dois processos filhos tentem escrever a mesmo tempo
int Atual[5]; //tb uma pra cada um
//vamos setar a estrutura local com infomacoes da nossa maquina
TSocket = socket(AF_INET,SOCK_STREAM,0);

local.sin_family = AF_INET;
local.sin_port = htons(3506);
local.sin_addr.s_addr = INADDR_ANY; //enderco local
bzero(&(local.sin_zero),8);

//usar o misterioso bind
bind(TSocket,(struct sockaddr *)&local,sizeof(struct sockaddr));

//agora a funcao listem ela e bem simple
listen(TSocket,5); //o segundo parametro 5 e o numero de conexoes que vamos esperar (max)
tamanho = sizeof(struct sockaddr_in);
while (Next < 5)
{
if ((Clientes[Next] = accept(TSocket,(struct sockaddr *)&cliente[Next],&tamanho)) < 0)
{
printf("Erro\n");
exit(0);
}
else
{
printf("Cliente se conectou numero: %d, ip:%s\n",Next,inet_ntoa(cliente[Next].sin_addr));
if (!fork())
{
int coisa = Next;
while(1)
{
if (recv(Clientes[coisa],recived_msg,20,0) < 0)
{
printf("Erro ao receber msg\n");
exit(0);
}
else
{
printf("Msg Recebida:%s\n",recived_msg);
exit(0);
}
}

}
Next++;
}
}
}
//o fork que faz o bicho pegar o resto nem e divertido
//imagine nosso servidor tendo que segurar 50 conexoes
//ai a conexao de algum kra anda bem lenta se o as nossas
//checagens ficassem todas num loop ia atrapalhar o andamento
//de todo servidor por isso criamos um novo processo com o fork
//ele se comunica com o pai claro mas a coisa nao e tao simples
//assim agora vou escrever um aplicativo interativo pra ser jogado
//entre no minimo 3 pessoas um servidor e dois clientes
////pra gente testar todas as singularidades espero
//que essa parte da trasnmissao ja lhe seja util de algo
//qualquer coisa sabe como me encontrar
//comando pra compilar $gcc servidor.c -o servidor
//mais uma coisa isso nao ta funcionando corretamente
//pois c os 5 servidores tiverem conectados ao mesmo tempo
//ele so vai ler o Next que e cinco isso e um problema com
//o fork que eu to tentando resolver eu queria uma fariavel
//que so fosse assecivel pelo processo filho atraves do PID..

particularmente prefiro o SDL_net é multiplataforma e mais simples de se usar.
nem estou pensando em multiplayer agora, só to publicando o que ta no bau.

1 comentário:

MontyOnTheRun disse...

Noooossa! lembra da gente testando essa bagaça?
ante-ontem acabei re-escrevendo tudo do zero e agora to fazendo testes usando pipes de UNIX. Agora eu juro que implemento um multiplayer legal =-)

(lembrando que depois, pra trocar de pipes pra sockets é tranquilo).