[Resolvido] SDL_net server-client - C++ - Portugal-a-Programar
By seuqram, February 15, 2016 in C++
Boa Tarde. Há poucos dias resolvi começar a fazer um servidor-client a utilizar o SDL_net.
Tenho que ter um protocolo rápido (UDP), onde pode haver perdas, e outro protocolo à parte, que confirme todos os pacotes.
O problema está no segundo. Eu achei muito desafiador fazer esse protocolo através de um sistema baseado no UDP (enviar até receber um feed-back) mas eu estou com receio de que isso possa ficar muito pesado e assim, não o possa utilizar.
O sistema consiste num buffer no client que guarda os pacotes que ainda não foram confirmados dentro de um vetor de string. Eu testei enviar uns 200 pacotes por segundo o que até 30 segundos pareceu tudo normal... Depois, de repente, a conexão é interrompida (o servidor continua ativo). Desligando e tentando ligar o servidor, diz "não foi capaz de se ligar ao port" (o port está no "3114"). Tenho que desligar o servidor e ligá-lo outra vez para volta a dar.
Eu, no codigo, quando envio os pacotes, tenho sempre o canal como -1, ou seja não uso canais individuais para os enviar.
Será que se fazendo uso deles, isto irá ficar mais rápido?
Provavelmente estou a fazer alguma coisa de mal no sistema, será que há modelos de tranformação de UDP->TCP melhores que o buffer/feed-back?
Será que eu devo utilizar os protocolos do SDL_net, TCP e UDP juntos sem andar a inventar coisas?
Ou esta pode ser mesmo uma limitação do meu computador/router?
Edited February 23, 2016 by pwseo
removida formatação desnecessária
Depois, de repente, a conexão é interrompida (o servidor continua ativo). Desligando e tentando ligar o servidor, diz "não foi capaz de se ligar ao port" (o port está no "3114"). Tenho que desligar o servidor e ligá-lo outra vez para volta a dar.[/font]
isso tem aspecto normal de um problema grave de código.
é perfeitamente normal quando uma aplicação estoira, a porta fica "pendurada" até o sistema operativo achar que deve libertar a porta novamente.
sim, existe. e como tal, podes ver o que o TCP faz : https://en.wikipedia.org/wiki/Sliding_window_protocol
estás a fazer para aprender ou para usar ?
se for para aprender, força. se for para usar, não inventes a roda.
aplicação estoira
O servidor pára provavelmente... pelo excesso de pacotes num pequeno intervalo de tempo?
Eu também tive um ideia parecida. Mas e se nenhum pacote chegasse? Já não podia informar os que faltavam. E mesmo que chegasse um ou dois, o feed back para o client também se podia perder. Ou estará a faltar-me alguma coisa?
Eu estou a tentar fazer um projeto completo. Estou a fazer para aprender, mas ao mesmo tempo para utilizar.
Andei a pesquisar muito, e a maioria da informação que encontro, fazem rivalidade entre o UDP e o TCP, dizem que um é mais rápido que o outro, etc... Dizem que utilizar os protocolos ao mesmo tempo pode meter a ligação mais lenta do que se fosse apenas UDP. E apontam para, quando se precisa de pacotes seguros, fazer uma costumização do UDP.
Na verdade há algumas funcionalidades do TCP que eu não queria o tempo todo, como por exemplo a sequencialização dos pacotes, ou a ligação por stream que eu penso que tire um pouco de velocidade?
Mas eu não sou nenhum expert na coisa, e por isso não sei se conseguia fazer isto tudo como deve ser. O que é que me aconcelha? Utilizar os dois juntos não vai aumentar assim lá muito a latência?
Obrigado pela boa resposta.
Edited February 17, 2016 by seuqram
não, a aplicação estoira por outra razão qualquer.
o problema não é pelo número de pacotes que dizes enviar.
em UDP tens sempre o problema de um pacote não chegar.
é para isso que o TCP serve : fiabilidade de envio de informação.
isso parece muita conversa de quem não percebe da coisa. é capaz de ter lido qualquer coisa aqui ou ali e já passou a ser um doutor da coisa (porque isto é um país de doutores).
os dois protocolos de comunicação existem e servem os seus propósitos.
se querem uma ligação em que a fiabilidade de chagada de informação é essencial, então usa TCP, caso contrário, usa o UDP.
se queres uma coisa intermédia usa os dois !!!.
pelo que dizes, o que queres fazer é como disse anteriormente, usa os dois.
terás de criar um protocolo ao nível da aplicação que usa pacotes vindos de duas portas (uma a usar o protocolo UDP e outra o protocolo TCP)
se necessitares, envia-me o teu código que eu dou uma vista de olhos
Uhmm! Estou a ver. Assim a tarefa torna-se muito mais fácil :] Têm de ser necessáriamente em ports diferentes? Ou é pelo facto de ser mais rápido?
E esqueceu-se das aspas numas palavras aí que disse... eheh, e obrigado, Já me safou de muito tempo, que eu podia ter gasto a seguir essas informações da treta.
sim, se queres usar os dois protocolos, tens de usar duas portas diferentes. uma porta configurada para usar o UDP e outra para o TCP.
e passa a ser da tua responsabilidade (ao nível da aplicação) a ordenação de pacotes entre as duas portas.
Eu não quero estar a ser muito incomodativo mas eu tenho outro problema (sincronização do tcp com o udp) que eu não consigo resolver e não encontro nenhuma pista de como o fazer.
Anteriormente, eu tinha uma função que, quando recebia um pacote udp e se não houvesse nenhum usuário com o endereço do pacote, o servidor criava um novo usuário com esse novo endereço. Isto porque eu identificava facilmente o host e o port do client através do UDPpacket:
UDPpacket *p;
User[...].host = p->address.host;
User[...].port = p->address.port;
Mas agora que instalei o tcp com o udp, tirei essa função, aceitando novas conexões com o SDLNet_TCP_Accept. Assim consigo criar sockets de tcp que liguem o servidor com o client, mas não consigo saber nada acerca da conexão udp. (O endereço remoto)
Eu já tentei a função: SDLNet_TCP_GetPeerAddress (no servidor) para saber o port do client, mas deu-me um port diferente do que me dá no UDPpacket. E também tentei o SDLNet_UDP_GetPeerAddress no client para saber o port e assim envia-lo para o servidor, só essa função só me dá o port local.
Se me conseguissem dar umas dicas, agradecia.
Edited February 21, 2016 by seuqram
disponibiliza o teu código
Eu andei a pesquisar muito... e eles dizem que se o client estiver por detrás do NAT, não vai ser possivel achar o port remoto sem haver troca de um packet de UDP. Eles estão certos?
Provavelmente vou ter que:
(server) enviar o numero de identificação para o client por tcp depois de ter aceitado a conexão.
(client) recebe o pacote, e até receber um segundo de tcp, vai enviar udps com o numero de identificação.
(server) recebe um de udp, e muda o port do usuário correspondente ao numero de identificação que recebeu no pacote.