Jump to content
João S. Ferreira

Comunicação cliente servidor via socket C++

Recommended Posts

João S. Ferreira

Boa Noite

Já já fiz o programa cliente e servidor e se correr na nossa máquina ele funciona e faz o pedido. O problema é quando tento correr por exemplo o servidor no meu computador em casa e o meu colega correr o cliente em casa dele.

A ligação não chega se quer acontecer... Será que me poderiam dizer o que estou a fazer mal ou o que devo fazer para que a ligação funcione

client.cpp

#include <iostream>
#include "wrappers.h"
using namespace std;

void Jogo_RUN(int Sockfd); //
void Initquadro(char quadro[QUADRO_SIZE][QUADRO_SIZE]); // Inicializar quadro
void DisplayClientUsage(char exe[]); // Coloca no ecrã a informação de utilização do programa cliente
void Desenharquadro(char quadro[QUADRO_SIZE][QUADRO_SIZE]); // Desenhar quadro
void CHALLENGERMove(char quadro[QUADRO_SIZE][QUADRO_SIZE]); // Coloca no quadro a jogada do CHALLENGER

int main(int argc, char *argv[])
{
int Sockfd;
sockaddr_in ServAddr;
char ServHost[MAX_CHAR] = {}; // Host name.
hostent *HostPtr;
int port = DEFAULT_PORT; // Inicializa o porto por defeito
char *nome;
nome = (char*) malloc(MAX_CHAR*sizeof(char));
char yesno;

// Apenas executado o programa, usa o host e o porto por defeito
if (argc < 2)
{
strcpy(ServHost, DEFAULT_HOST);

port = DEFAULT_PORT;

cout << "\nUsing default host: " << DEFAULT_HOST;
cout << "\nUsing default port: " << DEFAULT_PORT;
}
// Host name foi especificado, usa esse host name e o porto por defeito
else if (argc == 2)
{
strcpy(ServHost, argv[1]);

port = DEFAULT_PORT;

cout << "\nUsing host: " << ServHost;
cout << "\nUsing default port: " << DEFAULT_PORT;
}
// Tanto o host name como o porto foram especificados, usa ambos
else if (argc == 3)
{
strcpy(ServHost, argv[1]);

port = atoi(argv[2]);

cout << "\nUsing host: " << ServHost;
cout << "\nUsing port: " << port;
}
else if (argc > 3)
{
cerr << "\nInvalid number of arguements.";

DisplayClientUsage(argv[0]);

return 1;
}
cout << "\nWho is challenging the champion?\nName: ";
cin.getline(nome, MAX_CHAR);

// Abra uma socket TCP
Sockfd = Socket(AF_INET, SOCK_STREAM, 0);

// Obtém o endereço do host.
HostPtr = Gethostbyname(ServHost);
cout<<"Address of a defender: ";
cout<< inet_ntoa(*((struct in_addr *)HostPtr->h_addr)) << "\n";
cout<<ServHost;

if (HostPtr->h_addrtype != AF_INET)
{
perror("\nUnknown host address");
exit(1);
}
memset((char*)&ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = ((struct in_addr*)HostPtr->h_addr_list[0])->s_addr;
//bcopy((char *)HostPtr->h_addr,(char *)&ServAddr.sin_addr.s_addr,HostPtr->h_length);
ServAddr.sin_port = htons(port);
// Connecta ao servidor
Connect(Sockfd, (sockaddr*)&ServAddr, sizeof(ServAddr));

// Entrega ao servidor o nome do CHALLENGER
write(Sockfd, nome, MAX_CHAR);

// Recebe a resposta do servidor se este aceita jogar ou não
read(Sockfd, &yesno, sizeof(yesno));

if(yesno == 'n'){
cout << "\nThe defender refused your challenge\n";
close(Sockfd);
return 0;
}

Jogo_RUN(Sockfd); // Corre o jogo

// Socket é fechada
close(Sockfd);
return 0;
}
// Corre o jogo
void Jogo_RUN(int Sockfd)
{
char estado = '\0';
char quadro[QUADRO_SIZE][QUADRO_SIZE]; // Cria o quadro
// Corre um jogo
for (int game = 0; game < TOTAL_GAMES; game++)
{
cout<<"\nThat defender accepted you're challenge!";
cout << "\n\n--------------------------------------------\n";

cout << "DEFENDER to start game.";
cout << "\n--------------------------------------------\n";
Initquadro(quadro); // Inicializa o quadro de jogo
// Continua os vários turnos até o servidor indicar que o jogo terminou
for (;
{
// Lê o estado do jogo e o quadro do jogo que é enviado pelo servidor
read(Sockfd, &estado, sizeof(estado));
read(Sockfd, quadro, sizeof(quadro));

// Recebe a jogada do CHALLENGER e mostra o quadro
if (estado == CLIENT_TURN)
{
cout <<"\nThe defender's move...";
Desenharquadro(quadro);
CHALLENGERMove(quadro);
Desenharquadro(quadro);

// Envia o quadro de volta ao servidor
write(Sockfd, quadro, sizeof(quadro));
}

// Jogo terminado
else
break;
}
cout << "\n--------------------------------------------\n";
Desenharquadro(quadro); // Desenha o quadro de jogo final
// Indica se o CHALLENGER ganhou/perdeu/empatou
if (estado == CHALLENGER_WINS)
cout << "\nCongratulations, you win!\n";

else if (estado == DEFENDER_WINS)
cout << "\nHaha, you lose!\n";

else
cout << "\nTie!\n";


}
cout << "\nMatch over!\n";
}

// Função que imprime no ecrã a informação de utilização do programa cliente
void DisplayClientUsage(char exe[])
{
cout << "\nUsage: " << exe << " [HOST] [PORT]";
cout << "\n\t-?, this usage information";
cout << "\n\nDefault host is " << DEFAULT_HOST << ".";
cout << "\nDefault port is " << DEFAULT_PORT << ".\n\n";
}
// Função que inicializa o quadro enchendo o quadro com caracteres vazios
void Initquadro(char quadro[QUADRO_SIZE][QUADRO_SIZE])
{
for (int i = 0; i < QUADRO_SIZE; i++)
for (int j = 0; j < QUADRO_SIZE; j++)
quadro[i][j] = BLANK;
}
// Função que imprime no ecrã o quadro com as jogadas do CHALLENGER e do DEFENDER
void Desenharquadro(char quadro[QUADRO_SIZE][QUADRO_SIZE])
{
/*cout << "\n\t 1 2 3";*/
cout << "\n\t -------------";
cout << "\n\t | " << quadro[0][0] << " | " << quadro[0][1] << " | " << quadro[0][2] << " |";
cout << "\n\t |---|---|---|";
cout << "\n\t | " << quadro[1][0] << " | " << quadro[1][1] << " | " << quadro[1][2] << " |";
cout << "\n\t |---|---|---|";
cout << "\n\t | " << quadro[2][0] << " | " << quadro[2][1] << " | " << quadro[2][2] << " |";
cout << "\n\t -------------\n";
}
// Função que recebe e executa a jogada do CHALLENGER
void CHALLENGERMove(char quadro[QUADRO_SIZE][QUADRO_SIZE])
{

short coluna = 0, linha = 0;
bool valido = false;

do
{
cout << "\nYour move... "; // Recebe a jogada do utilizador através do nº de linha e coluna do quadro
cout << "\nLine (1 to 3): ";
cin >> linha;
cout << "\nColumn (1 to 3): ";
cin >> coluna;

// Avalia se os valores de linha/coluna introduzidos são válidos
if ((quadro[linha-1][(coluna-1)] == BLANK) && ((linha-1) >= 0) &&
((linha-1) < QUADRO_SIZE) && ((coluna - 1) >= 0) && ((coluna - 1) < QUADRO_SIZE))
valido = true;

else // Limpa o buffer e diz ao utilizador para tentar outra vez
{
cout << "\nInvalid move, try again.";

cin.clear();
cin.ignore(MAX_CHAR, '\n');
}
} while (!valido); // Continua o ciclo até o CHALLENGER indicar uma jogada válida
quadro[linha-1][(coluna-1)] = CHALLENGER_CH; // Executa a jogada do CHALLENGER
}

Server.cpp

#include <iostream>
#include <fstream>
#include "wrappers.h"
#include <ctime>
using namespace std;

void DisplayServerUsage(char exe[]); // Coloca no ecrã a informação de utilização do programa servidor
void Initquadro(char quadro[QUADRO_SIZE][QUADRO_SIZE]); // Inicializa o quadro de jogo
void UserMove(char quadro[QUADRO_SIZE][QUADRO_SIZE]); // Recebe a jogada do utilizador e coloca no quadro
void Desenhaquadro(char quadro[QUADRO_SIZE][QUADRO_SIZE]); // Desenha o quadro
bool BoardWon(char quadro[QUADRO_SIZE][QUADRO_SIZE], char testCh); // Devolve true se alguém ganhou/empatou
void Jogo_RUN(int NewSockfd, char *challengerName); // Corre o jogo com o cliente

int main(int argc, char *argv[])
{
int Sockfd, NewSockfd;
int port = DEFAULT_PORT; // Define o porto por defeito.
int value=1;
socklen_t ClntLen;
sockaddr_in ClntAddr, ServAddr;
char yesno;
char challengerName[MAX_CHAR] = {};

// Porto especificado, então usa esse porto
if (argc == 2)
port = atoi(argv[1]);
// Número inválido de argumentos no comando, imprime no ecrã a informação de utilização e termina
else if (argc > 2)
{
cerr << "\nInvalid number of arguements.";

DisplayServerUsage(argv[0]);

return 1;
}
// Abre uma socket TCP
Sockfd = Socket(AF_INET, SOCK_STREAM, 0);
// A opção SO_REUSEADDR permite ao servidor ser reiniciado com o mesmo endereço porto
//setsockopt(Sockfd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
// Liga o endereço local, assim o cliente pode conectar-se ao servidor
memset((char*)&ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
ServAddr.sin_port = htons(port);
Bind(Sockfd, (sockaddr*) &ServAddr, sizeof(ServAddr));
// "Escuta" a socket
Listen(Sockfd, 5);



// O servidor deve estar sempre a correr até o processo ser terminado
for(;
{
yesno = 'a';
// Espera por uma ligação do cliente
ClntLen = sizeof(ClntAddr);
NewSockfd = Accept(Sockfd, (sockaddr*)&ClntAddr, &ClntLen); // Liga à maquina local
cout << "\nWaiting for a challenger...";
read(NewSockfd, challengerName, MAX_CHAR);

if (NewSockfd < 0)
perror("\nCan't bind to local address");

cout << "\nAccept challenge from " << challengerName << "? y/n ";
while(yesno != 'y' && yesno != 'n'){
cin >> yesno;
if(yesno != 'y' && yesno != 'n')
cout << "\nChoose yes or no";
}
// Envia ao cliente se o servidor aceita o desafio ou não
write(NewSockfd,&yesno,sizeof(yesno));

// Se aceitar começa o jogo
if(yesno == 'y')
Jogo_RUN(NewSockfd,challengerName);

}
return 0; // Não deve acontecer
}
// Corre o Jogo
void Jogo_RUN(int NewSockfd, char *challengerName)
{
char quadro[QUADRO_SIZE][QUADRO_SIZE]; // Cria o quadro
// Faz com que gere sempre um número aleatório novo para cada processo filho cliente
srand(time(NULL));
Initquadro(quadro); // Inicializa o quadro
int numMoves = 0; // Contador qusado para verificação de empate
bool challengerWins = false, defenderWins = false, tie = false;
// Corre até o jogo terminar
for (;
{
Desenhaquadro(quadro);
UserMove(quadro); // Jogada do Defender
Desenhaquadro(quadro);
cout <<"\nThe challenger's move...";

if (BoardWon(quadro, DEFENDER_CH)) // Jogo ganho pelo Defender
{
 defenderWins = true;
 break; // Sai do ciclo
}

else if (++numMoves == MAX_MOVES) // Se houver empate sai do ciclo
{
 tie = true;
 break;
}

//Recebe a jogada do Challenger
write(NewSockfd, &CLIENT_TURN, sizeof(CLIENT_TURN));
write(NewSockfd, quadro, sizeof(quadro));
read(NewSockfd, quadro, sizeof(quadro));

if (BoardWon(quadro, CHALLENGER_CH)) // Jogo ganho pelo Challenger
{
 challengerWins = true;

 break; // Sai do ciclo
}

else if (++numMoves == MAX_MOVES) // Se houver empate sai do ciclo
{
 tie = true;
 break;
}
}

if (challengerWins) // Vitória do Challenger
{
// Envia ao cliente o resultado
write(NewSockfd, &CHALLENGER_WINS, sizeof(CHALLENGER_WINS));
}
else if (defenderWins) // Vitória do Defender
write(NewSockfd, &DEFENDER_WINS, sizeof(DEFENDER_WINS));

else // Comunica um empate
write(NewSockfd, &TIE, sizeof(TIE));
// Envia ao cliente o quadro
write(NewSockfd, quadro, sizeof(quadro));


}
// Limpa um filho zombie, pode acontecer
extern "C" void SigChldHandler(int sig)
{
// Recebe os sinais SIGCHLD, então os processos filhos não se tornam zombies
while (wait3(NULL, WNOHANG, NULL) > 0)
;
}
// Função que imprima informação de utilização do programa servidor
void DisplayServerUsage(char exe[])
{
cout << "\nUsage: " << exe << " [port]";
cout << "\n\nDefault port is " << DEFAULT_PORT << ".\n\n";
}
// Função que incializa o quadro, enchendo o mesmo com caracteres vazios
void Initquadro(char quadro[QUADRO_SIZE][QUADRO_SIZE])
{
for (int i = 0; i < QUADRO_SIZE; i++)
for (int j = 0; j < QUADRO_SIZE; j++)
quadro[i][j] = BLANK;
}

// Função que imprime no ecrã o quadro de jogo com as jogadas do challenger/defender
void Desenhaquadro(char quadro[QUADRO_SIZE][QUADRO_SIZE])
{
/*cout << "\n\t 1 2 3";*/
cout << "\n\t -------------";
cout << "\n\t | " << quadro[0][0] << " | " << quadro[0][1] << " | " << quadro[0][2] << " |";
cout << "\n\t |---|---|---|";
cout << "\n\t | " << quadro[1][0] << " | " << quadro[1][1] << " | " << quadro[1][2] << " |";
cout << "\n\t |---|---|---|";
cout << "\n\t | " << quadro[2][0] << " | " << quadro[2][1] << " | " << quadro[2][2] << " |";
cout << "\n\t -------------\n";
}
// Função que recebe e executa a jogada do utilizador
void UserMove(char quadro[QUADRO_SIZE][QUADRO_SIZE])
{
short linha = 0;
short coluna = 0;
bool valido = false;

do
{
cout << "\nYour move... "; // Recebe a jogada do utilizador através do nº de linha e coluna do quadro
cout << "\nLine (1 to 3): ";
cin >> linha;
cout << "\nColumn (1 to 3): ";
cin >> coluna;


// Avalia se os valores de linha/coluna introduzidos são válidos
if ((quadro[linha-1][(coluna-1)] == BLANK) && ((linha-1) >= 0) &&
((linha-1) < QUADRO_SIZE) && ((coluna - 1) >= 0) && ((coluna - 1) < QUADRO_SIZE))
valido = true;

else // Limpa o buffer e diz ao utilizador para tentar outra vez
{
cout << "\nInvalid move, try again.";

cin.clear();
cin.ignore(MAX_CHAR, '\n');
}
} while (!valido); // Continua o ciclo até o defender indicar uma jogada válida
quadro[linha-1][(coluna-1)] = DEFENDER_CH; // Executa a jogada do Defender
}

// Função que verifica se o quadro já foi ganho.
bool BoardWon(char quadro[QUADRO_SIZE][QUADRO_SIZE], char testCh)
{
// Verifica para as linhas o caracter testCh.
for (int i = 0; i < QUADRO_SIZE; i++)
if ((quadro[i][0] == testCh) && (quadro[i][1] == testCh) && (quadro[i][2] == testCh))
return true;
// Verifica para as colunas o caracter testCh.
for (int i = 0; i < QUADRO_SIZE; i++)
if ((quadro[0][i] == testCh) && (quadro[1][i] == testCh) && (quadro[2][i] == testCh))
return true;
// Verifica para as diagonais o caracter testCh
if ((quadro[0][0] == quadro[1][1]) && (quadro[1][1] == quadro[2][2]) && (quadro[0][0] == testCh))
return true;
if ((quadro[2][0] == quadro[1][1]) && (quadro[1][1] == quadro[0][2]) && (quadro[2][0] == testCh))
return true;
return false; // Devolve falso se o quadro ainda não foi ganho
}

Edited by Rui Carlos
GeSHi

Share this post


Link to post
Share on other sites
Rui Carlos

Configuraste os routers para fazer redirecionamento de tráfego nas redes internas? Se funciona localmente, à partida isso é problema de configuração da rede.

Share this post


Link to post
Share on other sites
João S. Ferreira

Estive a ver no router e finalmente consegui colocar a funcionar. Era mesmo problema de portforwarding

Obrigado

P.S: Já agora como faço para colocar o código com as cores com que colocou?

Edited by João S. Ferreira

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.