eduinfo10
(usa Ubuntu)
Enviado em 09/04/2014 - 21:14h
Boa Noite Pessoal,
Preciso fazer uma espécie de QUIZ com sockets.
Consegui fazer boa parte do código.
A idéia é a seguinte:
O cliente responde 10 perguntas (operações matemáticas), logo que ele coloca o valor da conta, este valor vai para o servidor, e lá compara se a resposta corresponde ao resultado, se corresponder, manda uma mensagem de correto para o cliente e conta 1 para depois no fim poder dizer quantas ele acertou, e o mesmo procedimento é feito se o cara errar a conta.
Só não estou conseguindo mandar para o cliente o valor dos contadores, pois os contadores são "int", e o socket só envia tipo "char". Já tentei converter usando a função sprintf, mas não rolou. Alguem me da uma luz ? Vou postar o código do cliente e do servidor logo abaixo. Lembrando que tudo está correto, apenas preciso arrumar o final dos dois códigos, para enviar o resultado dos contadores para o cliente. E não faço a menor ideia como faz ...
Obrigado.
***************************************** Servidor ***************************************
/*--------------------------------------------
Função que usa o TCP para receber uma mensagem
do cliente. O parametro de entrada desta função
é o número da porta do socket
----------------------------------------------*/
#include <stdio.h> //printf e scanf
#include <stdlib.h> //exit
#include <string.h> //sizeof
#include <unistd.h>
#include <sys/types.h> //tipos de dados para chamadas de sistemas
#include <sys/socket.h> //estrutura de dados para sockets (structs)
#include <netinet/in.h> //estrutura de dados para acesso a internet (structs)
/*--------------------------------------------
função chamada quando ocorre um erro
em uma chamada de sistema
----------------------------------------------*/
void error(const char *msg) //inicio da função
{
perror(msg); //função que apresenta mensagem na tela sobre o erro
exit(1); //termina o processo
} //fim da função
/*--------------------------------------------
função main que recebe o número
da porta como parametro
----------------------------------------------*/
int main(int argc,char *argv[])
{
/*--------------------------------------------
sockfd: socket file description
- cada processo tem um número que representa
uma linha na tabela descritora de arquivos
- recebe valor da chamada de sistema socket
newsockfd: new socket file description
- recebe valor da chamada de sistema accept
portno: guarda o número da porta usada pelo
servidor para aceitar as conexões
----------------------------------------------*/
int sockfd, newsockfd, portno;
socklen_t clilen;//registro que guarda o tamanho do endereço do cliente
char buffer[256];//buffer para guardar caracteres lidos do socket
char respostas[10][100];
int aux=0;
int contacertos = 0;
int conterros = 0;
strcpy (respostas[0], "4") ;
strcpy (respostas[1], "6");
strcpy (respostas[2], "16");
strcpy (respostas[3], "49");
strcpy (respostas[4], "64");
strcpy (respostas[5], "81");
strcpy (respostas[6], "0");
strcpy (respostas[7], "1");
strcpy (respostas[8], "100");
strcpy (respostas[9], "16");
/*--------------------------------------------
sockaddr: struct que guarda endereço internet
struct sockaddr_in
{
short sin_family; --> deve ser AF_INET
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8]; --> não é usado
};
----------------------------------------------*/
struct sockaddr_in serv_addr, cli_addr;
/*--------------------------------------------
serv_addr:endereço do servidor
cli_addr:endereço do cliente conectado com o servidor
----------------------------------------------*/
int n;
if(argc<2) //se número da porta recebido for menor do que 2
{
//exibe mensagem de erro
fprintf(stderr,"Numero da porta nao fornecido ou incorreto\n");
exit(1);//termina o processo
} //fim do if
/*--------------------------------------------
chamada de sistema --> socket(a,b,c)
- a:AF_UNIX(emdereço domínio unix)
ou AF_INET(endereço domínio internet)
- b:SOCK_STREAM(stream de dados)
ou SOCK_DGRAM(pacotes de dados)
- c:0(permite ao sistema opercaional definir
o melhor protocolo entre IP, TCP e UDP)
----------------------------------------------*/
/*abre o socket e joga em sockfd o número da
linha da tabela descritora de arquivos */
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0) error("Erro de abertura do socket");
//se linha menor que 0 exibir mensagem de erro
/*--------------------------------------------
bzero(a,b): buffer 0 - função que inicializa buffer com zeros
- a:ponteiro para o buffer
- b:tamanho do buffer
----------------------------------------------*/
//inicializa buffer serv_addr com zeros
bzero((char *) &serv_addr, sizeof(serv_addr));
//atoi(argv[1]):converte a string armazenada
//no vetor argv[] em um numero inteiro
portno=atoi(argv[1]);
//portno recebe o número da porta que o servidor vai ouvir
serv_addr.sin_family=AF_INET;
//recebe endereço domínio internet (obrigatório)
//unsigned long s_addr: recebe o IP do host
//INADDR_ANY: possui o endereço IP da máquina corrente
serv_addr.sin_addr.s_addr=INADDR_ANY;//recebe o endereço IP do host onde está o servidor
//htons: host to network - converte o numero da porta
//do computador para o numero usado na rede - conversão em byte ordem
serv_addr.sin_port=htons(portno);//recebe o número da porta usado na rede (net byte order)
/*--------------------------------------------
bind(a,b,c)
- a:numero da linha do descritor de arquivos
- b:endereço internet do servidor
- c:tamanho do endereço internet do servidor
----------------------------------------------*/
if(bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr))<0)
//se o bind não conseguiu amarrar o endereço ao socket
error("Erro no bind - o endereço não foi atado ao socket");//mensagem na tela com o erro
/*--------------------------------------------
listen(a,b)
- a:numero da linha do descritor de arquivos
- b:numero máximo de conexões que podem ficar
esperando para serem ouvidas
----------------------------------------------*/
listen(sockfd,5); //o servidor ouve pelo socket
clilen=sizeof(cli_addr);//clilen recebe o tamanho do endereço do cliente
/*--------------------------------------------
accept(a,b,c): bloqueia o serviço até conexão com um cliente
- a:socket file description
- b:endereço do cliente conectado
- c:tamanho do endereço do cliente
----------------------------------------------*/
newsockfd=accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if(newsockfd<0)
//se novo endereço do socket menor do que 0, mensagem de erro
error("Erro ao aceitar conexao");
bzero(buffer,256); //inicializando buffer com zeros
do
{
/*--------------------------------------------
read(a,b,c)
- a:novo endereço socket
- b:buffer
- c:número máximo de caracteres lidos
- n:recebe a quantidade de caracteres lidos
----------------------------------------------*/
n = read(newsockfd,buffer,255);
if (n<0)
//se nada foi lido do socket, mensagem de erro
error("Erro de leitura do socket");
printf("Resposta: %s\n",buffer);//exibe na tela a mensagem contida no buffer
/*--------------------------------------------
write(a,b,c)
- a:novo endereço socket
- b:mensagem
- c:tamanho da mensagem
- n:recebe o número de caracteres enviados
pelo write ao cliente
----------------------------------------------*/
//Comecei a mexer aqui //
int teste;
//teste = strcmp(buffer[1],"4") ;
//printf("teste: %d\n",o);
if(atoi(buffer)==atoi(respostas[aux])){
contacertos++;
n = write(newsockfd,"correta a questao",200);
}else
{ n = write(newsockfd,"resposta errada",200);
conterros++;
}
if(n<0)
//se nada foi escrito no socket, mensagem de erro
error("Erro de escrita para o socket");
aux++;
}
// Limita para 10 perguntas
while(aux<10);
char auxstring[256];
sprintf(auxstring, "%d",conterros);
write(newsockfd,auxstring,200);
close(newsockfd); //fecha novo endereço
close(sockfd); //fecha endereço do servidor
return 0; //retorna 0 para o sistema operacional
} //fim da função main
****************************************** cliente *****************************************
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> //tem a struct hostent
/*--------------------------------------------
função chamada quando ocorre um erro em uma chamada de sistema
----------------------------------------------*/
void error(const char *msg)
{
perror(msg);
exit(0);
} //fim da função
/*--------------------------------------------
função main que recebe nome do host
servidor e o número da porta
----------------------------------------------*/
int main(int argc, char *argv[])
{
int sockfd, portno, n;
char perguntas[10][100];
int aux=0;
strcpy (perguntas[0],"2 + 2");
strcpy (perguntas[1],"3 + 3");
strcpy (perguntas[2],"8 + 8");
strcpy (perguntas[3],"7 * 7");
strcpy (perguntas[4],"8 * 8");
strcpy (perguntas[5],"9 * 9");
strcpy (perguntas[6],"7 - 7");
strcpy (perguntas[7],"4 / 4");
strcpy (perguntas[8],"10 *10");
strcpy (perguntas[9],"12 + 4");
//vai conter o endereço do servidor que será conectado
struct sockaddr_in serv_addr;
/*--------------------------------------------
struct hostent
{
char *h_name; //nome oficial do host
char **h_aliases; //alias
int h_addrtype; //tipo de endereço
int h_length; //comprimento do endereço
char **h_addr_list; //lista de endereço do name server
#define h_addr h_addr_list[0] //endereço de compatibilidade
};
----------------------------------------------*/
//server:ponteiro para a struct hostent que tem o endereço do host na internet
struct hostent *server;
char buffer[256];
if(argc<3)//se parametros de entrada incorretos, mensagem de erro e sai do cliente
{
fprintf(stderr,"Erro - uso da porta do host número %s\n", argv[0]);exit(0);
}
portno=atoi(argv[2]); //pega o número da porta
sockfd=socket(AF_INET, SOCK_STREAM, 0); //pega o socket file description
if(sockfd<0)
error("Erro na abertura do socket");//se file description<0, mensagem de erro
//server recebeinformações sobre o host pelo gethostbyname(vetor com o nome do host)
server=gethostbyname(argv[1]);
if(server==NULL)
{
fprintf(stderr,"Erro, host não encontrado\n");
exit(0);
} //se host não encontrado, mensagem de erro e sai do processo
bzero((char *) &serv_addr, sizeof(serv_addr)); //inicializa buffer serv_adder com zeros
serv_addr.sin_family = AF_INET; //recebe o endereço domínio internet (obrigatório)
//copia de_addr para sin_addr
bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
serv_addr.sin_port=htons(portno); //sin_port=numero da porta já convertido para rede
/*--------------------------------------------
connect(a,b,c)
- a:socket file description
- b:endereço do host que o cliente quer buscar serviço
- c:tamanho deste endereço
----------------------------------------------*/
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr))<0)
//se não conseguiu conectar com o servidor
error("Erro de conexão"); //mensagem de erro
do
{
printf ("\n %s",perguntas[aux]);
printf("\n Responda a questao: ");
bzero(buffer,256);//zera o buffer
fgets(buffer,255,stdin);//pega pela entrada padrão os caracteres
aux++;
//grava através do socket o conteúdo do buffer, no comprimento da mensagem enviada
n=write(sockfd,buffer,strlen(buffer));
if(n<0)
//se n<0 erro de escrita no socket e mensagem de erro
error("Erro ao escrever no socket");
bzero(buffer,256);//zera o buffer novamente
//le através do socket (bloqueante) e joga o conteúdo no buffer até 255 caracteres
n=read(sockfd,buffer,255);
if(n<0)
//se n<0 erro de leitura no socket e mensagem na tela
error("Erro ao ler do socket");
printf("%s\n",buffer); //exibe conteúdo do buffer na tela
}
while(aux<10);
printf("\n");
bzero(buffer,256);//zera o buffer
read(sockfd,buffer,255);
printf("%s \n valor do buffer\n",buffer);
close(sockfd); //fecha o socket
return 0; //retorna 0 para o sistema operacional
} //fim do main