paulo1205
(usa Ubuntu)
Enviado em 28/10/2012 - 02:49h
Você colocou no seu programa código para indicar erros. Quais erros estão sendo indicados?
Alguns problemas no seu código:
1) Em
cliente.sin_family = AF_INET;
cliente.sin_port = htons(PORTA);
, onde você ajusta o endereço onde ele vai escutar?
2) Em
while((sock = accept(sock,0,0))==SOCKET_ERROR)
{}
, o socket devolvido por
accept é distinto do socket original. Do jeito como está, o listener continua aberto, mas você vai perder a referência a ele no momento em que a sobrescrever com o valor do socket da conexão estabelecida (ou de erro). Trabalhe, portanto, com duas variáveis, mesmo que você tenha a intenção de fechar o listener depois de receber a conexão.
Ainda a esse respeito, o que, exatamente, você pretende com esse loop? Digamos que dê erro no
accept () (por exemplo, porque a chamada a
listen () falhou -- e o retorno dessa função você esqueceu de testar). Nesse caso, você vai ficar preso nesse loop, até porque, depois da primeira chamada a
accept (),
sock não vai mais ter o valor do socket listener.
3) Em
//Recebe mensagem com nome do oponente
bytes = recv(sock, oponente, sizeof(oponente), 0);
, o tipo de
oponente é ponteiro para char. Numa arquitetura de 32 bits, isso significa que
sizeof(oponente) será igual a 4 (e se for 64 bits, então o tamanho será 8). Tem certeza de que é realmente
sizeof(oponente) que você quer usar?
4) Em
if(bytes < 0)
{
sprintf(erro, "Nenhum dado recebido! conexao encerrada.");
return -1;
}
, você não quis dizer
if(bytes<=0) ? Ou, ainda, algo como o seguinte código?
if(bytes==0){
/* Fim da conexão. Pode ser errado do ponto de vista do
protocolo do seu programa, mas não houve erro em recv(). */
}
else if(bytes<0){
/* Erro em recv() */
}
else{ /* bytes será necessariamente >0 */
/* Alguns dados recebidos sem erro, mas não quer dizer que estajam
todos adequados ao protocolo da aplicação. Você ainda deve
validá-los antes de os utilizar. Em particular, se você pediu
para ler x bytes, mas chegaram x-1 bytes, você provavelmente
terá problemas. Melhor mesmo seria comparar o valor de 'bytes'
com um valor exato do tamanho esperado da mensagem. */
}
5) Em
char ptrm[sizeof(ptr)];
itoa(ptr, ptrm, 10);
, você errou feio. se eu quiser jogar 2147483647 partidas, isso caberá num inteiro de 4 bytes, mas os seus dez algarismos (mais o byte nulo) não caberão na string de quatro bytes que você tentou criar em
prtm .
Outro problema com esse pedaço é o uso de
itoa (). Essa função não é padronizada, não existe em todos os compiladores e -- o que é pior de tudo -- não verifica se a conversão do número vai caber dentro da string, podendo corromper a memória do seu programa. Não use esse lixo.
6) Em
send(sock, player, sizeof(player), 0); //Envia mensagem com o nome do player
send(sock, ptrm, sizeof(ptrm), 0); //quantidade de partidas
, o que seu programa faz se alguma dessas chamadas a
send () falhar?
No programa de conexão, há os seguintes problemas:
1) Em
char prtd[sizeof(int)];
e o respectivo
recv (), mais a diante, temos o outro lado da moeda do problema 5 do outro programa. Aqui também você deveria usar um tamanho que o deixe mais confortável para trabalhar com segurança.
2) Em
cliente.sin_addr.s_addr=inet_addr(ip);
, eu gosto mais de usar
inet_aton () que tem um melhor diagnóstico de erro.
3) Em
send(sock, player, sizeof(player), 0);
, você também deveria verificar a ocorrência de erros.
4) Em
bytes = recv(sock, oponente, sizeof(oponente), 0); //Recebe mensagem com nome do oponente
bytes = recv(sock, prtd, sizeof(prtd), 0); //recebe quantas partidas serao jogadas
, valem novamente comentários sobre os tamanhos.
Possivelmente você gostaria de usar algo como
strlen(oponente) , ou mesmo
strlen(oponente)+1 , para saber onde temina o nome do oponente, sem confundir com o início da próxima mensagem. Mas melhor do que isso seria possivelmente ter um tamanho máximo para o nome do oponente (por exemplo, trinta caracteres), e sempre transmitir uma mensagem com trinta bytes para o nome; se o nome do oponente for "ze", que vão (ou venham) depois do nome vinte e oito bytes nulos -- qual o problema? Fazer isso é uma forma fácil de não ter de fazer um código ou protocolo complicado para lidar com dados de tamanho arbitrariamente variável.
Ainda, nessas linhas, você só trata a segunda mensagem, ignorando o valor retornado pela primeira. Por que não tratar cada uma?
5) Em
if(bytes < 0)
{
sprintf(erro, "Nenhum dado recebido! conexao encerrada.");
return -1;
}
, temos uma repetição do problema 4 do outro programa.
6) Em
return atoi(prtd);
, nenhum problema com o
atoi (esse é padrão e tem comportamento seguro e bem definido), mas o valor de
prtd é sujeito a problemas, como vimos acima.