sockets

1. sockets

Paulo
paulo_moc

(usa Ubuntu)

Enviado em 25/10/2012 - 22:07h

Olá pessoal, minha duvida é a seguinte : criei um cliente e um servidor, mas sempre que tento me conectar com o cliente ou o servidor fora da minha rede local, ele da erro e não consegue se conectar, já criei alguns port scanners e alguns programas com requisição http, e todos se conectam aos sites perfeitamente, mas quando se trata de meus propios programas se conectarem, eles nunca conseguem(exceto na rede aqui de casa), alguém poderia me ajudar com isso?

eu devo configurar alguma coisa para essa conexão?


  


2. Re: sockets

Perfil removido
removido

(usa Nenhuma)

Enviado em 26/10/2012 - 00:37h

shoxsz escreveu:

Olá pessoal, minha duvida é a seguinte : criei um cliente e um servidor, mas sempre que tento me conectar com o cliente ou o servidor fora da minha rede local, ele da erro e não consegue se conectar, já criei alguns port scanners e alguns programas com requisição http, e todos se conectam aos sites perfeitamente, mas quando se trata de meus propios programas se conectarem, eles nunca conseguem(exceto na rede aqui de casa), alguém poderia me ajudar com isso?

eu devo configurar alguma coisa para essa conexão?


@shoxcz: suas perguntas sempre me cheiraram a programas maliciosos mesmo, hmm. Mas nada contra, é um bom caminho também ;-) (caso negativo, ignore oaidshasdf)

Se ajudar:

Conexão reversa (o cliente acessa o teu servidor, servidor instalado na tua máquina)
Conexão cliente-servidor (cliente instalado na tua máquina, precisa ter a porta liberada no roteador, firewall e blabla)


3. Re: sockets

Paulo
paulo1205

(usa Ubuntu)

Enviado em 26/10/2012 - 02:20h

Nos tempos do Antigo Testamento, adivinhação era punida com morte.

Como eu não sou adivinho (e acho que ninguém aqui o é), que tal você pelo menos mostrar o código a respeito do qual quer ajuda?


4. Re: sockets

José Mário
miura 787

(usa Ubuntu)

Enviado em 26/10/2012 - 12:29h

Alguns sistemas como Sockets e RMI as vezes são bloqueados quando saem para rede externa pelos firewalls porque requisitam serviço por uma porta e respondem por outra(s) e ai o firewall bloqueia ou não consegue redirecionar o serviço pela porta (já que muda)!

Faça um teste preliminar, instale o hamachi ou algum serviço VPN que vc queira e rode o sistema indicando o IP da VPN e veja se vai funcionar!


5. Re: sockets

Paulo
paulo_moc

(usa Ubuntu)

Enviado em 26/10/2012 - 23:15h

hmm, na verdade, essa dúvida não nada maliciosa leolfm(mas abrirá algumas portas =])é um trabalho da escola, fazer um jogo da velha, o jogo ta pronto, mas queria fazer para os jogadores se conectarem através de outros pcs, então o programa funcionaria como servidor-cliente, sendo que a parte servidor determina a quantidade de partidas, o código para aguardar conexão é esse :

int aguarda_conexao(char* player, char* oponente, int ptr)
{

if((sock = socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR)
{
sprintf(erro, "Erro ao criar socket.");
return -1;
}

cliente.sin_family = AF_INET;
cliente.sin_port = htons(PORTA);

if(bind(sock(SOCKADDR*)&cliente,sizeof(cliente))==SOCKET_ERROR)
{
sprintf(erro, "Erro utilizar a funcao BIND.");
return -1;
}

listen(sock,1);

while((sock = accept(sock,0,0))==SOCKET_ERROR)
{}

//Recebe mensagem com nome do oponente
bytes = recv(sock, oponente, sizeof(oponente), 0);

if(bytes < 0)
{
sprintf(erro, "Nenhum dado recebido! conexao encerrada.");
return -1;
}

char ptrm[sizeof(ptr)];

itoa(ptr, ptrm, 10);

send(sock, player, sizeof(player), 0); //Envia mensagem com o nome do player
send(sock, ptrm, sizeof(ptrm), 0); //quantidade de partidas

return 0;
}


e o de conexão é esse :

int conectar(const char* ip, char* player, char* oponente)
{
char prtd[sizeof(int)];

if((sock = socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR)
{
sprintf(erro, "Erro ao criar socket");
return -1;
}

cliente.sin_family=AF_INET;
cliente.sin_port=htons(PORTA);
cliente.sin_addr.s_addr=inet_addr(ip);

if(connect(sock,(SOCKADDR*)&cliente,sizeof(cliente))==SOCKET_ERROR)
{
sprintf(erro, "Erro ao se conectar.");
return -1;
}

//Envia mensagem com o nome do player
send(sock, player, sizeof(player), 0);


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

if(bytes < 0)
{
sprintf(erro, "Nenhum dado recebido! conexao encerrada.");
return -1;
}

return atoi(prtd);
}

a porta usada é :
#defina PORTA 20000

a função para conexão retorna a quantidade de partidas porque é um menu que deve retornar a quantidade de partidas para a função main.



6. Re: sockets

Paulo
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.


7. Re: sockets

Paulo
paulo_moc

(usa Ubuntu)

Enviado em 28/10/2012 - 22:25h

Suas dicas me ajudaram bastante, consegui da uma melhorada no código, ainda não testei fora da minha rede, mas antes só apareciam os primeiros 4 bytes do nome, como voce disse que aconteceria, agora já consigo enviar o nome todo, e o código ta um pouco mais organizado(=]), e agora vou procurar um jeito de substituir o itoa, uma vez achei um código que tem a mesma função dela na net, porque nao tava compilando ela no linux, vo ve se uso ele com algumas mudanças.


___EDIT____
Mas ainda não foi possível estabelecer uma conexão fora da rede..., tudo que eu acho na internet sobre sockets, é o que esta no programa agora, mas ainda sim o programa não se conecta com outros computadores mais distantes, se puderem me mostrar uma forma de fazer isso eu agradeço.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts