SUJA - Servidor Universal para Jogos Amadores

Criando CLIENTES para o SUJA no Builder 3/4 ou posterior

(Usando a WINSOCK API - sem usar componentes VCL)

RECEITA

SUJA é um servidor para jogos - aqui há aqui uma descrição de como usá-lo e como programar um CLIENTE no Borland C++ BUILDER 

Importante: para este tutorial foi usado o Borland C++ Builder 4, mas qualquer outra versão deve funcionar sem problemas!

Ao invés de usar componentes prontos (VCL) de Internet da paleta de componentes, chamaremos diretamente a API do Windows WINSOCK2.H


Ingredientes

1 Form

4 Label

4 Edit

4 Button

1 Status Bar


Mode de preparo:

Coloque os componentes adequadamente dentro do Form1.

A seguir dê um duplo clique em cada um dos componentes abaixo listados, introduzindo o código colorido mostrado abaixo:

Button1:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   sockaddr_in RemoteSockAddr; // Data Structure for Socket Address

if((Socket=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
    {
    StatusBar1->SimpleText="socket Error "+IntToStr(WSAGetLastError())+"!";
    return;
    }
RemoteSockAddr.sin_family=AF_INET;
RemoteSockAddr.sin_addr.s_addr=inet_addr(Edit1->Text.c_str());
RemoteSockAddr.sin_port=htons(StrToInt(Edit2->Text));
if(connect(Socket,(sockaddr*)&RemoteSockAddr,sizeof(sockaddr_in))==SOCKET_ERROR)
    {
    StatusBar1->SimpleText="connect Error "+IntToStr(WSAGetLastError())+"!";
    return;
    }
else
    {
    if(WSAAsyncSelect(Socket,Button4->Handle,0x202,FD_READ)==SOCKET_ERROR)
        {
        StatusBar1->SimpleText="WSAAsyncSelect Error "+IntToStr(WSAGetLastError())+"!";
        return;
        }
    else
        {
        Edit4->Text="";
        Button1->Enabled=false;
        Button2->Enabled=true;
        Button3->Enabled=true;
        StatusBar1->SimpleText="Connected ...";
        }
    }
}

Button2:

void __fastcall TForm1::Button2Click(TObject *Sender)
{
 if(closesocket(Socket)==SOCKET_ERROR)
    {
    StatusBar1->SimpleText="closesocket Error "+IntToStr(WSAGetLastError())+"!";
    return;
    }
else
    {
    Button1->Enabled=true;
    Button2->Enabled=false;
    Button3->Enabled=false;
    StatusBar1->SimpleText="Disconnected ...";
    }
}

Button3:

void __fastcall TForm1::Button3Click(TObject *Sender)
{
 char buffer[256];< BR> int len;

strcpy(buffer,Edit3->Text.c_str());
if((len=send(Socket,buffer,strlen(buffer),0))==SOCKET_ERROR)
    {
    StatusBar1->SimpleText="send Error "+IntToStr(WSAGetLastError())+"!";
    return;
    }
else
    StatusBar1->SimpleText=IntToStr(len)+" bytes sent!";

}

Além disso no evento MouseUp do Button4 (Clique no componente Button4 dentro do Form, vá na aba Events do Object Inspector e procure o evento OnMouseUp , dando um duplo clique do lado direito dele) adicione para o evento o código abaixo:

void __fastcall TForm1::Button4MouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
char buffer[256];
int len;

if((len=recv(Socket,buffer,sizeof(buffer),0))==SOCKET_ERROR)
    {
    StatusBar1->SimpleText="recv Error "+IntToStr(WSAGetLastError())+"!";
    return;
    }
else
    {
    buffer[len]=0;
    Edit4->Text=StrPas(buffer);
    StatusBar1->SimpleText=IntToStr(len)+" bytes received!";
    }
}

No evento Close e Create do Form (Clique em uma área sem nenhum componente dentro do Form, vá na aba Events do Object Inspector e procure o evento OnClose e OnCreate , dando um duplo clique do lado direito dele) adicione para o evento o código abaixo:

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if(WSACleanup()==SOCKET_ERROR)
    StatusBar1->SimpleText="WSACleanup Error "+IntToStr(WSAGetLastError())+"!";
else
    StatusBar1->SimpleText="Winsock is stopped!";
   
}

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
WORD RequiredVersion=0x0002;
WSADATA WSAData;
int WSAStartupErrorCode;

if((WSAStartupErrorCode=WSAStartup(RequiredVersion,&WSAData))==0)
    StatusBar1->SimpleText="Winsock is started!";
else
    StatusBar1->SimpleText="WSAStartup Error "+IntToStr(WSAStartupErrorCode)+"!";
}

Trecho a acrescentar no início do código da Unit.cpp (só o código em vermelho o resto já está lá no Builder 4, em outras versões o código existente deve ser um pouco diferente):

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//------Meus includes--------------------------------
#include <winsock2.h>
SOCKET Socket;
//-------Fim Meus Includes--------------------------------

TForm1 *Form1;
//---------------------------------------------------------------------------

Modifique a propriedade Caption do form e dos componentes (botões e labels) e limpe a propriedade Text de cada Edit conforme a imagem:

Labels:

Label1

IP Address (Remote Host):

Label2

Port (Port Number):

Label3

Message to Send:

Label4

Message Received:

Buttons

Button1

Connect

Button2

Disconnect

Button3

Send

Propriedade Text de cada Edit

Edit1

127.0.0.1

Edit2

4001

Edit3

Mensagem Inicial!

Edit4

[vazio]

 


Mode de usar :

1) chame o programa SUJA (o servidor de jogos) antes de rodar o cliente acima programado. O servidor, quando ativo, deve listar os IPs da máquina em que ele está rodando, supondo que seja uma máquina ligada em rede ou conectada na Internet;

2) rode o programa CLIENTE acima criado em quantas máquinas da rede quiser. Como o programa vai se comunicar com outros programas da rede, o ideal é que haja mais de duas máquinas rodando cada cliente, mas com duas mmáquinas já é possível testar o programa. Modifique os campos Remote Host (servidor remoto em Edit1) para o valor de IP detectado pelo servidor SUJA. Modifique a PORTA (Port Number no Edit2) para a porta correntemente usada (4001, por exemplo) pelo SUJA. Clique no botão CONNECT;

3) se tudo der certo, o servidor SUJA deve detectar, para cada cliente rodando em rede, o número de conexões atual. Agora é só escrever uma mensagem no cliente no campo Message to Send  e clicar no botão Send (enviar). Todos os clientes conectados (inclusive quem está enviando a mensagem) receberão a mensagem enviada precedida do IP da máquina que a enviou.

Agora é com você! Use as mensagens enviadas para programar jogos em rede: ao invés de mensagens, cada cliente pode ser alterado para enviar posições ou jogadas de um jogo em andamento, além de detectar se a jogada é válida ou se alguém terminou/perdeu/ganhou o jogo! Você também pode alterar o programa para transformar os clientes em intercomunicadores pessoais, não esquecendo de inventar algum tipo de criptografia para seus programas-cliente!

Agora qualquer jogo online (seja de tabuleiro ou de ação) para jogadores em rede pode ser criado por você!


Copyright  Victor M. Sant'Anna  2007