seuqram Posted March 24, 2015 at 05:47 AM Report Share #580114 Posted March 24, 2015 at 05:47 AM (edited) Pessoal, estou a desenvolver um joguinho multiplayer com o winsock2 e com o opengl. Fiz uma versão teste do cliente na console aplication e correu tudo bem mas agora estou a ter algumas dificuldades em enquadrar o codigo com o resto do projeto. Fiz duas funções: a que iniciava o processo todo dos sockets... e outra para atualizar de frame em frame a troca de dados entre servidor/cliente. O problema é que, pelos vistos, ele só recebe os dados uma vez no inicio e depois para. As duas funções: #include "global.h" char buffer[uLTV+1]; void connect() { WSAData wsaData; if(WSAStartup(MAKEWORD(2,2),&wsaData)==SOCKET_ERROR) { printf("error de socket-1!\n"); } s=socket(AF_INET,SOCK_STREAM,0); if (s==INVALID_SOCKET) printf("socket e invalido!\n"); sockaddr_in you; you.sin_family=AF_INET; you.sin_addr.s_addr=inet_addr("127.0.0.1");// 85.245.61.211 // 192.168.10.2 you.sin_port=htons(20756); if(connect(s,(LPSOCKADDR)&you,sizeof(you))==-1) { WSACleanup(); printf("conexao falhou!!!\n"); system("pause"); } else { u_long iMode=1; ioctlsocket(s,FIONBIO,&iMode); buffer[uLTV]=10; buffer[0]=1; send(s,buffer,ULTV+1,0); } } void socketshare() { if(recv(s,buffer,ULTV+1,0)!=-1) { if(buffer[uLTV]==9) { buffer[uLTV]=NULL; float aa,bb,cc; int jogador; jogador=atoi((char*)strtok(buffer, "*")); xxj[jogador]=atof((char*)strtok(NULL, "*")); yyj[jogador]=atof((char*)strtok(NULL, "*")); zzj[jogador]=atof((char*)strtok(NULL, "*")); memset( buffer, NULL, sizeof(buffer)); }} sprintf(buffer,"%f*%f*%f*",xx,yy,zz); buffer[uLTV]=8; send(s,buffer,ULTV+1,0); memset( buffer, NULL, sizeof(buffer)); } Função Main: #include "global.h" int main(int argc, char **argv) { // init GLUT and create window glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(LadoTelax,LadoTelay); glutCreateWindow("3D World"); //keyboard and mouse func glutMouseFunc(mousepress); glutMotionFunc(camaramov); glutPassiveMotionFunc(camaramov); // register callbacks glutDisplayFunc(renderScene); glutReshapeFunc(changeSize); glutIdleFunc(renderScene); glEnable(GL_DEPTH_TEST); glutKeyboardUpFunc(keyup); glutKeyboardFunc(keydown); glutSpecialFunc(keybespecial); glutSetCursor(GLUT_CURSOR_NONE); glutTimerFunc(1000, FPS, 1); connect(); // enter GLUT event processing cycle glutMainLoop(); return 1; } A função connect é que supostamente inicia, a sockeshare a que troca os dados... esta é chamada pela função renderscreen para ser atualizada de frame em frame. Se conseguirem ver algum erro que me está a escapar ficaria muito agradecido 😛 Desde já obrigado. Edited March 24, 2015 at 10:37 AM by apocsantos geshi Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted March 24, 2015 at 06:51 AM Report Share #580115 Posted March 24, 2015 at 06:51 AM quais os sintomas que te levam a dizer que só executa uma vez ? IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
seuqram Posted March 24, 2015 at 02:57 PM Author Report Share #580139 Posted March 24, 2015 at 02:57 PM (edited) Bom dia, Quando executado 2 vezes o cliente, o primeiro não apanha as coordenadas da posição do jogador do segundo. O segundo vê apanha apenas uma vez, no inicio ,as coordenadas do primeiro ficando o boneco parado sem modificar a sua posição. Executando mais, vêem-se todos os outros anteriores parados sem movimento. Edited March 24, 2015 at 02:59 PM by seuqram Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted March 24, 2015 at 07:23 PM Report Share #580145 Posted March 24, 2015 at 07:23 PM (edited) Aplicacoes web.cliente/servidor sao como ter duas maos a bater palmas. Necessitas da mao direita e da esquerda. O problema e que apresentas o codigo de uma das maos PS desconfio que o problema esta no modelo bloqueante das chamadas, mas sem mais informacao e dificil dizer-lo con certeza Edited March 24, 2015 at 07:26 PM by HappyHippyHippo IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
seuqram Posted March 24, 2015 at 10:11 PM Author Report Share #580153 Posted March 24, 2015 at 10:11 PM (edited) É verdade Happy. O problema disto, eu acho, é que está em TCP, logo como envia de frame a frame as cordenadas e recebe muito mais devagar, os bonecos parecem parados. Estarei eu enganado? Andei a pesquisar e parece que para fazer uma conexao por UDP tenho que trocar os "send" por "sendto" e os "recv" por "recvfrom" e no server em vez de: me.sin_addr.s_addr=htonl(SOCK_STREAM); meter: me.sin_addr.s_addr=htonl(SOCK_DGRAM); Aqui está o codigo do servidor: #include<winsock2.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX_PLAYERS 30 #define MAX_ROOMS 1 #define ULTV 39 char nome[MAX_PLAYERS][15]; char getbuffer[uLTV+1]; char *buffer; char buffer2[15]; int quartosn=0; int playerstatus[MAX_PLAYERS]; char playerxyz[MAX_PLAYERS][35]; int main() { WSAData wsaData; if(WSAStartup(MAKEWORD(2,2),&wsaData)==SOCKET_ERROR) { printf("error de socket-1!\n"); return 0; } sockaddr_in me; sockaddr you[2]; me.sin_family=AF_INET; me.sin_addr.s_addr=htonl(SOCK_STREAM); me.sin_port=htons(20756); int s; s=socket(AF_INET,SOCK_DGRAM,0); if (s==INVALID_SOCKET) printf("socket e invalido!\n"); if(bind(s,(LPSOCKADDR)&me,sizeof(me))==-1){printf("erro ao abrir porta!\n");system("pause");return 1;} if(listen(s,1)==-1) { printf("ERROR a fazer listen!\n"); system("pause"); return 1; } int new_s[MAX_PLAYERS]; int quantos=0; int quantosv,quantosv2; int addr_size = sizeof (sockaddr); u_long iMode=1; ioctlsocket(s,FIONBIO,&iMode); //Instruções do servidor while(1) { new_s[quantos]=accept(s,NULL,NULL); if(new_s[quantos]!=INVALID_SOCKET){quantos++;} quantosv=-1; while(quantosv<quantos-1) { quantosv++; if(recv(new_s[quantosv],getbuffer,ULTV+1,0)!=-1) { if(getbuffer[uLTV]==1){FILE*User; buffer=(char*)strtok(getbuffer, "-"); User=fopen(buffer,"r");if(User!=NULL){memset( getbuffer, NULL, sizeof(getbuffer));getbuffer[uLTV]=2;send(new_s[quantosv],getbuffer,ULTV+1,0);}else {printf("%s foi registado\n",buffer);User=fopen(buffer,"w");buffer=(char*)strtok(NULL, "-");fwrite(buffer,sizeof(char),15,User);fclose(User);memset(getbuffer,NULL,sizeof(getbuffer));getbuffer[uLTV]=3;send(new_s[quantosv],getbuffer,ULTV+1,0);}} if(getbuffer[uLTV]==4){FILE*User; buffer=(char*)strtok(getbuffer, "-"); User=fopen(buffer,"r");if(User!=NULL){buffer=(char*)strtok(NULL, "-");fread(buffer2,sizeof(char),15,User);printf("%s",buffer);if(strcmp (buffer, buffer2) == 0){memset( getbuffer, NULL, sizeof(getbuffer));getbuffer[uLTV]=5;send(new_s[quantosv],getbuffer,ULTV+1,0);}else{memset( getbuffer, NULL, sizeof(getbuffer));getbuffer[uLTV]=6;send(new_s[quantosv],getbuffer,ULTV+1,0);}}else {memset( getbuffer, NULL, sizeof(getbuffer));getbuffer[uLTV]=6;send(new_s[quantosv],getbuffer,ULTV+1,0);}fclose(User);} if(getbuffer[uLTV]==7){quartosn++;} if(getbuffer[uLTV]==8){memset( playerxyz[quantosv], NULL, sizeof(playerxyz[quantosv]));getbuffer[uLTV]=NULL;sprintf(playerxyz[quantosv],"%s",getbuffer);memset( getbuffer, NULL, sizeof(getbuffer));} if(getbuffer[uLTV]==10){playerstatus[quantosv]=getbuffer[0];getbuffer[0]==NULL;} getbuffer[uLTV]=NULL; } if(playerstatus[quantosv]!=0) { quantosv2=-1; while(quantosv2<quantos-1) { quantosv2++; if(quantosv2!=quantosv&&playerstatus[quantosv]==playerstatus[quantosv2]) { sprintf(getbuffer,"%d*%s",quantosv,playerxyz[quantosv]); getbuffer[uLTV]=9; send(new_s[quantosv2],getbuffer,ULTV+1,0); printf("%s\n",buffer); memset( getbuffer, NULL, sizeof(getbuffer)); } } } } } } //getbuffer[uLTV]== //1-Chama o servidor para um Registro //2-Registo não aceite //3-Registo aceite //4-Pede ao servidor para logar //5-Logou com sucesso //6-Falhou a logar //7-Criar quarto //8-O server recebe as cordenadas dos jogadores //9-O server envia as cordenadas dos jogadores //10-Jogador entra num quarto O que é que me aconcelha fazer? Edited March 25, 2015 at 01:10 AM by apocsantos geshi Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted March 24, 2015 at 10:33 PM Report Share #580154 Posted March 24, 2015 at 10:33 PM como estava à espera. o teu problema é que o teu servidor está parado nesta instrução: new_s[quantos]=accept(s,NULL,NULL); o que quero dizer, é que enquanto o servidor não receber uma nova ligação, nunca irá retransmitir os dados para os clientes. se pretendes esse modelo de cliente/servidor, terás de ter no servidor dois threads, um para receber novas ligações e outro para fazer o broadcast das mensagens. existem outros modelos como o P2P, mas parece que necessitas de exercítar o teu código de rede primeiro 1 Report IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
seuqram Posted March 25, 2015 at 01:21 AM Author Report Share #580164 Posted March 25, 2015 at 01:21 AM (edited) Esse podia ser muito bem o problema. Como eu disse anteriormente eu fiz um teste no console aplication e dá para entender que o cliente está sempre a receber dados. Metento um printf no meio do loop do server ve-se que ele não para aí nessa instrução... O modelo que voce falou (P2P) ainda acho desnecessário pois ainda estou num grande começo do projeto. Edited March 25, 2015 at 01:21 AM by seuqram Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted March 25, 2015 at 01:44 AM Report Share #580165 Posted March 25, 2015 at 01:44 AM ok, já vi que tens ai o código para tornar o accept não bloquante. o teu código nºao só está incompreensívelmente mal estruturado como nem sequer está bem formatado, o que torna todo o processo de ler/interpretar o que tens muito complicado. devido a essa situação, entquanto não apresentares (pelo menos) o código bem indentado assim como toda a informação relevante (como o que raio é e para que serve o valor ULTV) não poderei ajudar mais IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
seuqram Posted March 25, 2015 at 02:26 AM Author Report Share #580166 Posted March 25, 2015 at 02:26 AM (edited) Desculpe lá... O codigo, sim está bem estruturado mas quando meto aqui no forum fica um bocadinho distorcido :S O ULTV é o ultimo valor da lista de variaveis getbuffer O valor ULTV+1 é o valor que vai determinar o tamanho da variavel getbuffer, por exemplo: getbuffer[40] ULTV=39 Este por sua vez (o ultimo valor da lista) é o que vai "explicar" do que se trata o conjunto de dados recebidos ou pelo cliente ou servidor. O "quantos" é a variavel do numero de clientes conectados. O "quantosv" é a variavel que percorre do 0 ao valor quantos para verificar o estado de dados de todas as conecções. O "quantosv2" é a variavel que percorre tambem todos esses numeros que serve para determinar a quem o programa deve enviar as cordenadas do [quantosv] jogador. O buffer é um ponteiro para dar auxilio ao getbuffer, este é o que será enviado/recebido. Eu penso que o server está corretamente logico. O problema ou está nas más definidas funções do client ou mesmo na ligação, que é TCP. Obrigado por abdicar do seu tempo. Edited March 25, 2015 at 02:33 AM by seuqram Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted March 25, 2015 at 03:32 AM Report Share #580167 Posted March 25, 2015 at 03:32 AM então vamos fazer assim em vez de estar a tentar ler um código todo desformatado, e tentar adivinhar o que não foi apresentado, coloca todo o teu código disponível em algum serviço online (tipo dropbox ou algo do género) para se poder ver e talvez testar IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
seuqram Posted March 25, 2015 at 04:27 AM Author Report Share #580168 Posted March 25, 2015 at 04:27 AM (edited) http://s000.tinyupload.com/index.php?file_id=08216118522950980374 Podes movimentar a camara com os butoes wasd, saltar com o space, por blocos com o botao lado direito do rato e tiralos com o esquerdo. Diverte-te 😛 ps:eu não sei se para rodar o executável precisa do dll do opengl glut. Edited March 25, 2015 at 05:00 AM by seuqram Link to comment Share on other sites More sharing options...
seuqram Posted March 25, 2015 at 11:30 PM Author Report Share #580224 Posted March 25, 2015 at 11:30 PM Como eu disse, o problema era de ser em TPC trocando na função do cliente: void socketshare() { if(recv(s,buffer,ULTV+1,0)!=-1) { if(buffer[ULTV]==9) { buffer[ULTV]=NULL; float aa,bb,cc; int jogador; jogador=atoi((char*)strtok(buffer, "*")); xxj[jogador]=atof((char*)strtok(NULL, "*")); yyj[jogador]=atof((char*)strtok(NULL, "*")); zzj[jogador]=atof((char*)strtok(NULL, "*")); memset( buffer, NULL, sizeof(buffer)); }} sprintf(buffer,"%f*%f*%f*",xx,yy,zz); buffer[ULTV]=8; send(s,buffer,ULTV+1,0); memset( buffer, NULL, sizeof(buffer)); } if(recv(s,buffer,ULTV+1,0)!=-1)-> while(recv(s,buffer,ULTV+1,0)!=-1) Assim ele recebe todos os dados que estão á espera de serem recebidos pela aplicação. Sabem, para fazer DNS dinamic, se preciso apenas de trocar o ip no client pelo nome do host? Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted March 26, 2015 at 06:29 AM Report Share #580230 Posted March 26, 2015 at 06:29 AM a alteração que fizeste não foi trocar o protocolo ... IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
seuqram Posted March 26, 2015 at 11:48 PM Author Report Share #580287 Posted March 26, 2015 at 11:48 PM (edited) sim eu sei. Mesmo por isso, como está em TCP tenho que meter o while para que ele leia os pacotes antigos e novos e não se atrase em relação ao servidor. em UDP eu acho que iria ser muito trabalhoso pois tinha que fazer outras funções para verificar se os pacotes tinham sido enviados e se não, reenvia-los... Apesar disso, quando eu testei o jogo com uns amigos meus, alguns dados foram perdidos :/ como por exemplo, eu no meu cliente metia um bloco, e por vezes no dele não aparecia a mudança... Edited March 26, 2015 at 11:57 PM by seuqram Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted March 27, 2015 at 08:21 AM Report Share #580298 Posted March 27, 2015 at 08:21 AM hehe ... não há nada como meter as mão na massa para aprender em primeira mão os problemas de uma escolha. agora só falta esperimentares com jogadores de outro continente para perceber o porquê da escolha de UDP por parte de muita gente ... ou então ter um jogo em que a necessitade de o tempo de resposta seja mais exigente IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
seuqram Posted March 27, 2015 at 10:27 PM Author Report Share #580367 Posted March 27, 2015 at 10:27 PM (edited) Fazem ideia de qual o fator que pode estar a condicionar o desaparecimento do enviar de certos dados para os clientes externos? visto que no servidor para o cliente no meu computador dá tudo certo. Edited March 27, 2015 at 10:36 PM by seuqram Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted March 27, 2015 at 11:47 PM Report Share #580374 Posted March 27, 2015 at 11:47 PM UDP é por sí só um protocolo onde se espera perdas de pacotes. quando testas localmente, a probsbilidade de perdas de pacotes é extremamente baixa. ao contrário do envio para o exterior onde o mesmo pacote necessita de viajar por imensos dispositivos que poderão eventualmente descartar o pacote devido a limites de buffer. (sim, routers ignoram pacotes para evitar buffer overflow) é por isso que para aplicações que não satisfacam as seguintes duas condições, o TCP é usado: - necessidade de tempo de processamento rápido (real time processing) - capacidade de recuperar de falhas/perdas de envio isto porque a maior parte do TCP, não é mais do que um processo de verificação e recuperação dessas mesmas falhas completamente transparente para as aplicações acima da stack 1 Report IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
seuqram Posted March 28, 2015 at 12:16 AM Author Report Share #580378 Posted March 28, 2015 at 12:16 AM Ok obrigado. Mesmo sendo em TCP, se houver um subcarga de pacotes, parte dos mesmos podem-se perder? Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted March 28, 2015 at 12:47 AM Report Share #580380 Posted March 28, 2015 at 12:47 AM Ok obrigado. Mesmo sendo em TCP, se houver um subcarga de pacotes, parte dos mesmos podem-se perder? sim ... ele perdem-se, mas o protocolo recupera-os por ti, não dás conta do processo. no entanto, tens de ter em conta que esse processo de verificação/recuperação é algo que atrasa a comunicação. não podes supor que um pacote recebido foi acabadinho de ser criado no computador que o enviou. 1 Report IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
seuqram Posted March 28, 2015 at 06:05 AM Author Report Share #580382 Posted March 28, 2015 at 06:05 AM (edited) Sabem, para fazer DNS dinamic, se preciso apenas de trocar o ip no client pelo nome do host? e mais uma coisa se não se importar de responder 😛 se um pacote mais pequeno for enviado de um ponto ao outro e esse ponto final estiver preparado para receber pacotes de maiores dimensões, o pacote é negado? exemplo: send(new_s[quantosv],getbuffer,10); recv(s,getbuffer,30); Edited March 28, 2015 at 06:08 AM by seuqram Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now