SUJA é um servidor para jogos - se você é programador BUILDER há aqui uma descrição de como usá-lo e programá-lo (no final da página)
Links
SUJA
MSG
CLIENTE para SUJA com fonte - feito no Builder 3 com componentes
(prontos) do Builder
MSG
Cliente com fonte - feito no Builder 4 sem usar os componentes de
Internet
Explicação dos programas acima:
SUJA_TCP_msg_server_com_VCLcomponentes
SUJA é um servidor que
repete as mensagens recebidas por ele para todos os clientes conectados.
A idéia
é deixar todo trabalho de tratamento de erros e recepção/filtragem de mensagens
com os "programas clientes".
Foi feito no Builder 3 porque nesta
versão gratuita tinha componentes capaz de executar essa tarefa. Na verdade é
uma adapatação de programas exemplos, tentei manter o mais simples possível, sem
alterar muito o código, já que o servidor precisa ser "universal". parte do
código eu aproveitei/traduzi do ConnecteInternet.cpp em
ftp://ftp-developpez.com/c/sources/bcb/codes/connecteinternet.zip
My_TCP_Message_Client
Os clientes (My_TCP_Message_Client) foram criados no
Builder 3 com uso dos componentes de Internet da Borland ou no Builder 4
sem a utilização de componentes específicos do Builder, já que eles não tinham
nenhum na versão gratuita...
A idéia é que ao conectar e enviar mensagens,
cada cliente conectado recebas as mensagens enviadas. Com isso é possível
construir programas que comuniquem-se uns com os outros. O problema desta
estratégia é que os programas clientes poderão ser programados para "trapacear",
já que o controle não sera feito pelo servidor. essa estratégia, entretanto,
garante menos "carga" para o servidor SUJA, que não terá muitas tarefas a
executar.
A mensagem que chega precisará ser filtrada: sempre chega a mensagem
encabeçada pelo número de IP
Só pode haver um cliente por máquina a não ser
que use portas diferentes;
também nada impede que haja mais de um servidor
usando portas diferentes;
Como usar: Inicie o SUJA (servidor) em um dos computadores da rede e veja o IP da máquina. Inicie a escuta. A seguir, em outros computadores da rede, rode os clientes, fornecendo o número da porta escolhida e o endereço de IP que o servidor SUJA detectou. Ao enviar uma mensagem qualquer pelos clientes, todos os outros clientes conectados recebem a mensagem e o número do IP da máquina que o enviou.
Caberia aos clientes detectar as mensagens que são para si, além de limpar a mensagem, deixando apenas a parte de texto.
A seguir, como foi programado o SUJA:
(usando o Borland C++ Builder 3)
Obs.: Utilizei o Builder 3 porque na minha versão gratuita é a que tinha a palete "Internet" com o ServerSocket. Qualquer versão que tenha a palete Internet instalada deve funcionar, provavelmente, mas neste caso, como este servidor será usado para *muitos* outros projetos, deixarei um executável compilado e disponível sem nenhum custo para os usuários (registrados ou não) do meu site "Receitas para Programadores".
Obs.: parte do código eu aproveitei/traduzi do ConnecteInternet.cpp em ftp://ftp-developpez.com/c/sources/bcb/codes/connecteinternet.zip
Ingredientes
1 Form
6 Label
1 ListBox
4 Edit
3 Button
1 Status Bar
1 ServerSocket
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)
{
ServerSocket1->Port=StrToInt(Edit1->Text);
ServerSocket1->Open();
Button1->Enabled=false;
Button2->Enabled=true;
StatusBar1->SimpleText="Server Started! Listening ...";
Edit4->Text=IntToStr(ServerSocket1->Socket->ActiveConnections);
}Button2:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
ServerSocket1->Close();
Button1->Enabled=true;
Button2->Enabled=false;
StatusBar1->SimpleText="Server Stopped!";
Edit4->Text=IntToStr(ServerSocket1->Socket->ActiveConnections);
}Button3:
void __fastcall TForm1::Button3Click(TObject *Sender)
{
AchaIP();
}Form:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
AchaIP();
}ServerSocket1:
void __fastcall TForm1::ServerSocket1ClientConnect(TObject *Sender,
TCustomWinSocket *Socket)
{
StatusBar1->SimpleText="Connected from "+Socket->RemoteAddress;
Edit4->Text=IntToStr(ServerSocket1->Socket->ActiveConnections);
}void __fastcall TForm1::ServerSocket1ClientDisconnect(TObject *Sender,
TCustomWinSocket *Socket)
{
Edit4->Text=IntToStr(ServerSocket1->Socket->ActiveConnections-1);
StatusBar1->SimpleText="Disconnected from"+Socket->RemoteAddress;
}void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
char buffer[256];
int len;
AnsiString Message;
int i;// Receive message
len=Socket->ReceiveBuf(buffer,255);
buffer[len]=0;
Edit2->Text=StrPas(buffer);
Edit3->Text=Socket->RemoteAddress;
StatusBar1->SimpleText=IntToStr(len)+" bytes received!";// Broadcast received message to all connected clients
Message=Socket->RemoteAddress+": "+StrPas(buffer);
strcpy(buffer,Message.c_str());
for(i=0;i<ServerSocket1->Socket->ActiveConnections;i++)
ServerSocket1->Socket->Connections[i]->SendBuf(buffer,strlen(buffer));
}
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
Port Number:
Label2
Message:
Label3
From:
Label4
Connections:
Label5
Esta Maquina:
Label6
IP: 0.0.0.0
Buttons
Button1
Start
Button2
Stop
Button3
Detectar IP
Propriedade Text de cada Edit
Edit1
4001
Edit2
[vazio]
Edit3
[vazio]
Edit4
0
Você ainda precisará acrescentar dois métodos no arquivo ".h" da sua Unit (no meu caso o arquivo de header chamava-se SUJAUnit.h)
class TForm1 : public TForm
{
__published: // IDE-managed Components
TLabel *Label1;
TLabel *Label2;
TLabel *Label3;
TLabel *Label4;
TEdit *Edit1;
TStatusBar *StatusBar1;
TEdit *Edit2;
TEdit *Edit3;
TButton *Button1;
TButton *Button2;
TEdit *Edit4;
TServerSocket *ServerSocket1;
TButton *Button3;
TLabel *Label5;
TLabel *Label6;
TListBox *ListBox1;
void __fastcall ServerSocket1ClientConnect(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall ServerSocket1ClientDisconnect(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
private: // User declarations
void AchaIP(void);
int VerConex(void);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};e no código da Unit ainda acrescentar:
int TForm1::VerConex(void)
{
int conectada=0;
typedef BOOL (WINAPI *PF_INETGETCONNECTEDSTATE)(LPDWORD, DWORD);
HANDLE hWinInet;
PF_INETGETCONNECTEDSTATE pfInternetGetConnectedState;
//.............
hWinInet = LoadLibrary("WININET.DLL"); //Chargement de la dll
if(hWinInet == NULL)
{
Label5->Caption = "Impossivel carregar Wininet.dll";
return conectada;
}
pfInternetGetConnectedState = (PF_INETGETCONNECTEDSTATE) GetProcAddress(
hWinInet, "InternetGetConnectedState");
// affectation du pointeur sur la fonction
if(pfInternetGetConnectedState == NULL)
{
Label5->Caption = "Erro chamando função InternetGetConnectedState";
if(hWinInet) FreeLibrary(hWinInet);
return conectada;
}
//.............
DWORD TypeCon ;
if (pfInternetGetConnectedState(&TypeCon, 0)) //appel de la fonction
{
Label5->Caption = "Conectado";
conectada=1;
}
else
{
Label5->Caption = "Não Conectado";
conectada=0;
}
//.............
if(hWinInet) FreeLibrary(hWinInet); //libération de la dll
//.............
return conectada;
}
// --------------------------------------------
// --------------------------------------------
void TForm1::AchaIP(void)
{
// para achar IP:
WORD wVersionRequested;
WSADATA wsaData;
char name[255];
AnsiString ip;
PHOSTENT hostinfo;
wVersionRequested = MAKEWORD( 1, 1 );if(WSAStartup( wVersionRequested, &wsaData ) == 0 && VerConex()==1)
{
if( gethostname ( name, sizeof(name)) == 0)
{
Label5->Caption = "Esta máquina: ";
Label5->Caption = Label5->Caption + name; //nom de l'ordinateur
if((hostinfo = gethostbyname(name)) != NULL)
{
ip = inet_ntoa (*(in_addr *)*hostinfo->h_addr_list);
Label6->Caption = "IP: " + ip; //adresse IP
////////// novo/
ListBox1->Items->Clear();
for (int i = 0; hostinfo->h_addr_list[i] != 0; ++i)
{
struct in_addr addr;
memcpy(&addr, hostinfo->h_addr_list[i], sizeof(struct in_addr));
ListBox1->Items->Add((String)inet_ntoa(addr));
}
ListBox1->Items->Add("127.0.0.1");
////////// fim novo/
}
}
WSACleanup( );
}
else
{
ListBox1->Items->Clear();
ListBox1->Items->Add("127.0.0.1");
}
}Em breve instruções para programação de CLIENTES que usem o SUJA (por enquanto use os arquivos fornecidos para entender seu funcionamento)
Copyright Victor M. Sant'Anna 2007