REMOTE MEMORY LIBRARY
Autores: Márcio
S. Pinho e Rafael S. Garcia
Contato: [email protected] e [email protected]
Versão: 2.0
Última
modificação: 27/Janeiro/2003.
OBJETIVO:
O
principal objetivo da biblioteca “Remote Memory” é permitir que o
usuário tenha a sua disposição uma memória de dados que pode ser compartilhada
entre programas que rodam em máquinas diferentes. A partir de uma aplicação
servidora, rodando em uma máquina remota, o usuário pode criar aplicações
clientes que se conectem a esse servidor e pode compartilhar dados entre as
aplicações.
O
diagrama a seguir mostra como funciona basicamente a biblioteca.
write
DOWNLOAD:
Clique
aqui para fazer o download dos arquivos
necessários para o Servidor.
Clique
aqui para fazer o download dos arquivos
necessários para o Cliente.
TCP/IP e
TCP/UDP:
O
conjunto de protocolos TCP/IP ( Transmission Control Protocol / Internal
Protocol ) são o pilar das comunicações na Internet. Este conjunto de
protocolos foi desenvolvido de forma a permitir a partilha de recursos entre os
diversos contituintes de uma rede.
O
TCP/IP é um protocolo estruturado por camadas, estando a camada TCP vem acima
da camada IP. A camada TCP gera o envio das mensagens, necessitando por vezes,
dividí-las em vários pacotes de tamanho apropriado. No receptor, a aplicação
que implementa a camada TCP será responsável pela sua reconstrução.
A
camada IP tem a responsabilidade de fazer chegar o pacote ao endereço IP de
destino. O pacote é entregue pela camada TCP juntamente com o endereço do
computador a que se destina. O IP proporciona um “serviço confiável de
datagramas” entre hosts.
O
UDP ( User Datagram Protocol ) faz a entrega de mensagens independentes,
designadas por datagramas, entre aplicações ou processos, em sistemas host.
O protocolo UDP não proporciona um “serviço confiável” de entrega de dados pois
os datagramas podem ser perdidos ou entregues fora de ordem.
enquanto que
o protocolo UDP (user Datagram Protocol) não proporciona uma serviço confiável
de entrega de dados.
COMO
COMPILAR:
Para
explicar como deve ser compilada a biblioteca, assumiremos que o usuário esteja
utilizando o software “Visual C++”.
Em
um primeiro momento, deve-se criar um novo projeto do tipo “Win32 Console
Application”. Em seguida, deve-se adicionar nas configurações do projeto a
biblioteca que contém as funções de rede. Para se fazer isso, deve-se clicar
com o botão direito do mouse em cima do nome do projeto e selecionar a opção “Settings...”
no menu que irá se abrir. Pode-se também selecionar o projeto e usar as teclas
de atalho “ATL + F7”. Na janela que irá se abrir, deve-se selecionar a
guia “Link” e no ítem “Category” deve-se selecionar a opção “General”.
Na área denominada “Object/Library modules” deve-se adicionar a
biblioteca “wsock32.lib”, exatamente como esta demonstrado na figura
abaixo.
Com
a Remote Memory Library é possível crair dois tipos de aplicação: servidora,
que armazena os dados, e cliente, que lê e altera esses dados.
Para
uma aplicação servidora deve-se adicionar os seguintes arquivos: “MemoryServer.cpp”
e “RemoteMemory.h”. Para adicionar esses arquivos no projetos, deve-se
clicar com o botão direito do mouse em cima do nome do projeto e selecionar “Add
Files to Project...” no menu que apareceu. Na janela que irá se abrir,
deve-se selecionar os dois arquivos já mencionados (e que, de preferência,
estejam no mesmo diretório do projeto) e clicar em “Ok”.
Para uma aplicação cliente, os
arquivos que devem ser adicionados ao projeto são: “MemoryClient.cpp” e “RemoteMemory.h”.
O processo para adicionar os arquivos é o mesmo descrito acima.
MONTANDO UMA APLICAÇÃO
CLIENTE:
Para descrever o processo de criação
de uma aplicação cliente, vamos assumir que o usuário esteja utilizando a
aplicação servidora padrão, distribuída juntatente com a biblioteca.
Para a criação de uma aplicação
cliente, o primeiro passo é adicionar os cabeçalhos da biblioteca “Remote
Memory Library” ao novo arquivo fonte. Para fazer isso, basta-se adicionar
a linha abaixo no começo do arquivo fonte da aplicação cliente:
#include "RemoteMemory.h"
Após isso, a primeira etapa da aplicação deve ser conectar o novo
cliente no servidor da memória remota compartilhada. O trecho de código a
seguir exemplifica como ficaria a função main:
void main ( int argc, char** argv ) {
if (argc < 2) {
printf ( "Command line
parameters: ServerIP\n" );
exit(1);
}
char
serverIP[30];
strcpy ( serverIP, argv[1] );
int result = ConnectToRemoteMemory ( serverIP );
if ( !result ) {
printf ( "Unable to connect to Memory Server at %s.\n\n", serverIP
);
exit (0);
}
O valor retornado pela função é 1 quando a consegue estabelecer a conexão e 0 quando da erro. O parâmetro serverIP da
função é uma “string” que indica o endereço ou o número IP da máquina
onde a aplicação servidora deve estar rodando. Por exemplo, se a aplicação
servidora está sendo executada na mesma máquina que a aplicação cliente, esse
parâmetro será 127.0.0.1 ou localhost. Essa função abre dois tipos de conexão com o servidor: uma conexão
via TCP/IP e a outra via TCP/UDP. O usuário poderá usar funções dos dois tipos
de conexão no mesmo programa sem problemas.
A partir desse ponto, o usuário
poderá desenvolver a aplicação da maneira que achar mais adequada para as suas
necessidades.
Para gravar dados na memória remota
compartilhada de dados, o usuário poderá usar uma das duas funções abaixo:
·
void WriteOnRemoteMemoryIP (void
*message, WORD address, int size)
·
void WriteOnRemoteMemoryUDP (void *message, WORD address, int size)
A
primeira função grava o dado na memória remota
compartilhada através da conexão via
TCP/IP enquanto que a segunda função grava o dado via TCP/UDP. Os parâmetros
para as duas funções são os seguintes:
· message: o dado que será enviado para o
servidor e gravado na memória remota compartilhada.
· address: o endereço da memória remota compartilhada
onde esse dado deve ser gravado.
· size: o tamanho (em bytes) do dado que será
gravado.
É
importante que o usuário entenda como se constitui a memória remota
compartilhada para trabalhar corretamente com ela. Cada posição da memória remota compartilhada
equivale a 1 byte. Logo, para se gravar 3 valores inteiros em sequência não se
pode utilizar, por exemplo, os endereços 3, 4 e 5. Se o usuário fizer isso, não terá os dados
corretos quando for feita uma leitura desses valores. O mais indicado a fazer,
nesse caso, seria gravar os dados nos endereços 3 * sizeof(int), 4 * sizeof(int) e 5 * sizeof(int). Com isso, o usuário garante que terá seus
três valores gravados em sequência e os dados esterão corretos.
Para
ler dados da memória remota compartilhada, as funções são as seguintes:
·
void ReadFromRemoteMemoryIP (void *message, WORD address, int size)
·
void ReadFromRemoteMemoryUDP(void *message, WORD address, int size)
Novamente, a primeira função lê o
dado da memória remota compartilhada através ad conexão TCP/IP enquanto que a
segunda lê o dado via TCP/UDP. Os parâmetros são os seuintes:
· message: onde o dado será armazenado
quando for lido.
· address: o endereço da memória remota compartilhada
onde esse dado deve ser gravado.
· size: o tamanho (em bytes) do dado que será
gravado.
Clique aqui para fazer o download de um exemplo de
aplicação cliente. Essa aplicação exibe dois cubos em OpenGL que ficam rodando
na tela. Os valores de incremento ou decremento dessas rotações são lidos da
memória remota compartilhada via TCP/IP. As teclas ‘a’, ‘s’, ‘d’, ‘w’, ‘z’ e
‘x’ aumentam ou diminuem os valores das rotações nos três eixos. Cada vez que
uma tecla é pressionada, o valor é alterado e gravado na memória remota
compartilhada via TCP/UDP.
A aplicação acima utiliza as
biblotecas gráficas OpenGL e GLUT. Caso seja necessário, detalhes sobre estas
ferramentas podem ser obtidos no endereço http://www.inf.pucrs.br/~pinho/CG/Aulas/OpenGL/OpenGL.html.