|
Usuários |
|
168 Usuários Online
|
|
[Artigos]
Sockets |
Publicado por ActiveDelphi : Segunda, Julho 18, 2005 - 11:44 GMT-3 (42442 leituras)
34 Comentários Enviar para um amigo Versão para impressão
|
Bem, talvez você já tenha rodado bastante em busca de algo sobre sockets no Delphi, e acho que você vai gostar bastante do conteúdo encontrado neste artigo...

Introdução
Bem, talvez você já tenha rodado bastante em busca de
algo sobre sockets no Delphi, e acho que você vai gostar bastante do conteúdo
encontrado neste artigo. Falando um pouco sobre mim: Meu nome é João Nelson
Lima, trabalhei com Delphi em uma empresa de automação comercial durante 1 ano e
seis meses. Mas antes já utilizava o Delphi, mas nada de forma profissional,
vamos dizer assim. Hoje tenho 22 anos e moro em Fortaleza. Sou estudante do
CEFET – CE. Meu e-mail é jnelson3@ig.com.br. E assim como você, enfrento os
mesmo problemas para encontrar conteúdos avançados de Delphi. Por isso resolvi
passar meus conhecimentos para os interessados. E por favor se alguém for mudar
ou publicar me comunique. Dúvidas e sugestões são bem vindas. Por fim gostaria
de desejar a você, caro leitor, uma excelente leitura e um aprendizado útil e
empolgante.
Instalando os compoentes no Delphi
7
Para isso vá
no menu Component | Install Packages... Na janela que ira surgir clique no botão
Add... e procure pelo arquivo dclsockets70.bpl. De OK e pronto! Os componentes
irão aparecer na palleta Internet.
Agora vamos direto ao Assunto
TserverSocket – Este componente como o nome já diz é o SERVIDOR. Ele
será responsável por receber as conexões. De quem? Dos TClientSocket! É
importante perceber este conceito em que cada TclientSocket conecta a um e
somente um servidor. Sempre que você quiser fazer uma comunicação usara no
mínimo um Server e um Client (Vamos passar a chamá-los assim OK?) Um outro
detalhe super importante é que no caso do servidor ele recebe um integer de
conexões.
Configuração mínima:

O circulo maior representa o server e
o quadrado pequeno é o cliente.
TclientSocket – Este
componente como o nome já diz é o CLIENTE. É com ele que conectamos aos
servidores. Pense nele como a janela do seu browser. Com ele podemos nos
conectar em qualquer servidor. Mas para isso temos que fazer alguns ajustes que
veremos a seguir. Por enquanto é importante pegar o conceito de que cada Client
se liga somente e diretamente a um Server e o Server poder receber vários
Clients. De cara pode surgir a seguinte duvida: Ora, se o client está ligado no
servidor como faço para ele falar com outro client ??? Não tem saída meu caro!
Sempre vai passar pelo servidor, não há mágica, o que vai acontecer que iremos
informar ao servidor o destinatário final da mensagem quando o servidor receber
e “perceber” que a mensagem deve se entregue a outro Client, ele irá enviar uma
mensagem ao Client correspondente. Isso é o protocolo de comunicação, ele é
pessoal e cada um vai implementar como achar melhor.
Iniciando a comunicação
Irei primeiro explicar as conexões simples, que tem no
exemplo do Delphi. Esta conexão simples serve apenas para comunicar um cliente a
um servidor e vice versa.
Neste projeto iremos construir duas aplicações, uma servidora e outra cliente,
com o objetivo de fazer um Chat.
Por questões didáticas iremos começar pelo servidor que
terá a medíocre missão de confirmar uma informação recebida.
Com o Delphi aperto e um novo projeto iniciado
colocaremos somente o componente TServerSocket e iremos alterar as propriedade
PORT para 2255 e NAME para Servidor. Teremos:

É claro que
o número da porta pode usar outro, mas por padrão adotei este aleatoriamente.
Agora vamos configurar os eventos. Primeiro os do
componente depois o Form1. No componente TServerSocket que iremos chamar de
Server ou componente Servidor, iremos programar o evento OnClientRead. Este
evento é acionado sempre que chaga algo no servidor, isto é, sempre que um
cliente envia algum dado.
Como já foi dito antes nossa aplicação ira apenas
confirmar que recebeu algo, então iremos deixar a procedure assim:
procedure TForm1.ServidorClientRead(Sender:
TObject; Socket: TCustomWinSocket);
begin
Servidor.Socket.Connections[0].SendText('Recebi algo');
end;
Isso fará com que que o servidor ao receber qualquer dado, envie uma resposta,
ou seja uma string contendo “Recebi algo” para a primeira conexão.
Para inicio precisamos agora somente ativar nosso Servidor. Então o evento
OnCreate do Form deve ficar assim:
procedure TForm1.Form1Create(Sender: TObject);
begin
Servidor.Active := True;
End;
Agora vamos para o lado do Cliente. Para isso devemos
iniciar uma nova aplicação. E colocaremos o componente TclientSocket, um memo,
um Button, e um edit. O arranjo dos componentes é 100% pessoal mas o meu ficou
com essa cara:

Com os
componentes posicionados, iremos alterar algumas propriedade básicas. De cara
temos que mudar o NAME do TClientSocket para CLIENTE e iremos atribuir o
mesmo valor que foi dado a propriedade Port do servido para a do cliente
isso é 2255. e claro o Address(endereço) que vai ser o o IP, no nosso caso o
127.0.0.1 que é o de LOOPBACK, pois as duas aplicações rodarão na mesma
maquina.
Iremos programar os comando de envio e recebimento de
mensagens no formato string =) com isso já conseguiremos fazer um chat, mas
somente entre as duas aplicações, para que possamos adicionar mais pessoas
teremos que modificar a maneira como o servidor vai gerenciar as conexões e isso
requer mais cuidados, conceito de alocação dinâmica e ponteiros. Que veremos
mais adiante.
O Edit1 vai ser a entrada de texto que vai ser enviada
o botão vai executar o procedimento para enviar e no memo guardaremos as
respostas do servidor.
Observe os códigos e veja como é simples:
Evendo OnClick do Botão:
Procedure TForm1.Button1Click(Sender: TObject);
begin
CLIENTE.Socket.SendText(Edit1.Text);
end ;
Evento onRead do TclientSocket:
procedure TForm1.ClienteRead(Sender: TObject; Socket: TCustomWinSocket);
begin
Memo1.Lines.Add(Socket.ReceiveText);
end;
E claro a ativação do servidor no onCreate do Form1:
procedure TForm1.FormCreate(Sender: TObject);
begin
CLIENTE.Open;
end;
Meu caro agora você já pode rodar as duas aplicações e ver o que acontece.
Lembre-se que PRIMEIRO RODE O SERVIDOR e depois o cliente. Fácil perceber o
porque.
Indo alem
Iremos agora dar um passo a frente, vamos ver como colocar mais um cliente
conectado no servidor.
Experimente rodar duas vezes o aplicativo cliente, observe que a conexão é
efetivada e que você pode a partir deste segundo cliente enviar mensagens para o
servidor, mas quanto ao recebimento da resposta, todos vão para o o primeiro =/
e somente vai para o segundo se o primeiro sair. Teste! Experimente.... e
comprove
Parando pra pensar
Ficou fácil notar que aquele 0 (Zero) no comando lá em cima usado para enviar
uma resposta pra o cliente se refere ao numero da conexão destino.
Servidor.Socket.Connections[0].SendText('Recebi algo');
Isso é uma contagem direta que o servidor faz começa no 0 e vai até o limite do
tipo INTEGER. Quando entra um ele passa a ser o ZERO se entrar outro passa a ser
o 1 e outro passa a ser o 2 e assim por diante, isso muda se alguém sair, é como
uma pilha quem está em cima do que saiu cai uma posição. Assim se o que tava na
posição um desconectar o ZERO não se altera mais a partir do DOIS todos caem uma
posição e logo o que era 2 passa a ser o UM.
Vamos imaginar a seguinte situação, o usuário A se conectou logo então ele pegou
a posição 0(zero), isso quer dizer que sempre que enviar o comando
Servidor.Socket.Connections[0].SendText(’qualquer texto aqui dentro’);
Esse texto então só vai para o usuário A. Agora o usuário B entra e caso nos
queremos enviar uma mensagem para B temos que informar index 1 assim:
Servidor.Socket.Connections[1].SendText(’qualquer texto aqui dentro’);
Fica extremamente obvio que no caso de um usuário C entrar o index deve ser 2,
logo temos uma rotina pra que o servidor envie o que receber para todos os
usuários. Isso é temos o principio de um principio de programa de chat =)
Agora toda mensagem que chegar no servidor, ao invés de ser apenas confirmada
vai ser retornada a todos os usuários que a ele estão conectados.
Iremos modificar o evento OnClientRead para que fique assim:
procedure TForm1.ServidorClientRead(Sender: TObject; Socket: TCustomWinSocket);
Var MsgRecebida : String;
I : integer;
begin
MsgRecebida := socket.ReceiveText; // Pega o conteúdo enviado
For i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
Serversocket1.Socket.Connections[i].SendText(MsgRecebida);
end;
Simples não é? Pegamos o conteúdo que foi enviado, e mandamos para todos os
conectados no momento. Inclusive ao usuário que mando a mensagem. Isso é...
Fizemos um Chat. Sugiro que coloque mais um Edit na aplicação cliente para que
sirva como um campo para o Nick dos usuários e agora no evento de clique do
botão ajuste para enviar o “nick” da pessoa, por exemplo:
‘<’+Edit2.text+’> ’ +edit1.text;
Muito simples =) realmente sim. O problema é que normalmente temos que enviar
dados específicos para cada usuário, sentimos essa necessidade logo que pensamos
em fazer uns sistema com logon, em que se pede senha, teremos q confirmar se o
usuário está liberado ou não. Outra necessidade é quando temos que enviar
mensagem em modo privado. Isso temos que saber quem é quem nas conexões.
Entendeu isso? Se nosso gerenciador de conexões não coordenar direitinho quem
cai quem ta na posição 0, 1, 2 e etc podemos ter complicações serias. Se você
tentar mandar mensagem para uma conexão que não existe certamente vai dar pau e
se você não coordenar estas conexões de forma eficiente provavelmente uma
mensagem que ia pra FULANO pode ira pra o BELTRANO.
Entendido esta etapa temos que somente agora aprender a como gerenciar isso.
Vamos então criar um GC ou seja o gerenciador de conexões.
O Primeiro passo é saber como vamos organizar as conexões. A idéia base é gerar
é identificar cada conexão com um código e armazenar em uma estrutura igual a
pilha de conexões do componente assim sendo quando algum cliente conectar
adicionaremos a nossa estrutura o código da conexão, quando sair deletamos, caso
queiramos enviar uma mensagem particular procuramos em nossa estrutura
identificamos a posição, e enviaremos =)
Iniciando o gerenciador de conexões
Analisamos o que o Delphi nos trás, encontrei o TList que é uma estrutura pronta
para gerenciar ponteiros em pilha. Para gerar os códigos iremos usar ponteiros
até porque é a forma de identificarmos os usuários quando conectam, desconectam
ou enviam mensagens. Através da propriedade DATA.
Declarei a variável
IDConexoes : TList;
No evento onCreate do form principal criei o IDConexoes assim:
IDConexoes := TList.Create;
IDConexoes.Clear;
No evento OnClose do form principal liberei ele da memória assim:
IDConexoes.Free;
Agora vamos a parte que requer mais atenção, iremos programar o evento On
ClientConnect e o OnClientDisconnect.
Primeiro a conexão do cliente:
procedure TForm1.ServidorClientConnect(Sender:
TObject; Socket: TCustomWinSocket);
Var IDsocket : ^byte;
begin
New(IDSocket);
Socket.Data := IDSocket;
IDConexoes.Add(Socket.data);
end;
O que fiz foi simplificar ao máximo. Criei uma variável local como ponteiro,
reservei um ponteiro novo para a conexão informei que o ponteiro pertence a ela
e adicionei o endereço na nossa lista.
Agora o procedimento de desconexão
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
Var NumConex : integer;
Begin
IDConexoes.Remove(Socket.Data);
Dispose(Socket.Data);
end;
Percebeu como esse TList é show? Ele faz tudo sozinho!
Como localizar o cliente....
Para finalizar vamos ver como responder somente para o cliente que enviou a
mensagem. Por exemplo, suponhamos que estejam conectados os usuários A, B e C,
mas não sabemos quem está em qual posição. Mas está registrado as entradas no
nosso TList (IDConexoes). E temos que enviar uma mensagem resposta para o
cliente B como. Vamos admitir que sempre que ele escrever ‘HORAS?’ vamos enviar
uma string com a hora atual. Ok? A pergunta que teima em pairar no ar é “Como
saber o INDEX dele?” Para responder temos que voltar para o evento onClientRead,
mas e antes iremos criar a função LocalizaCliente, assim:
Function TForm1.LocalizaCliente(Cli : Pointer):Integer;
Begin
Result := IDConexoes.IndexOf(Cli);
End;
Agora sim vamos ao evento :
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
Var Msg : String;
IDCli : integer;
HoraStr : String;
begin
Msg := socket.ReceiveText;
If Msg = ‘HORA?’ then
Begin
IDCli := LocalizaCliente(Socket.Data);
HoraStr := FormatDateTime('HH:mm:ss',Now);
If (IDCli >= 0) then
Servidor.Socket.Connections[IDCli].SendText(HoraStr);
end;
end;
Moleza não? Espero que tenha ficado tudo claro.Esse assunto é muito extenso.
Espero que tenha esclarecido algo. Qualquer coisa podem me encontrar por e-mail
e no MSN Menssager também. Até +, forte abraço e tudo de bom,
Nelson Lima - Diretor Geral.
NeoSoft - “Seu futuro é o nosso presente”
|
|
Comentários | |
| | Comentários pertencem aos seus respectivos autores. Não somos responsáveis pelo seus conteúdos. |
por: rpessoa : Ago 02, 2005 - 11:22 (Informações sobre o membro | Enviar uma mensagem)
|
eu só não entendi essa parte :
Iniciando o gerenciador de conexões
Analisamos o que o Delphi nos trás, encontrei o TList que é uma estrutura pronta para gerenciar ponteiros em pilha. Para gerar os códigos iremos usar ponteiros até porque é a forma de identificarmos os usuários quando conectam, desconectam ou enviam mensagens. Através da propriedade DATA.
Declarei a variável
IDConexoes : TList;
No evento onCreate do form principal criei o IDConexoes assim:
IDConexoes := TList.Create;
IDConexoes.Clear;
No evento OnClose do form principal liberei ele da memória assim:
IDConexoes.Free;
Aonde declarar ? Aonde colocar ?
desde já obrigado !!!
|
por: noobsaibot : Ago 22, 2005 - 02:21 (Informações sobre o membro | Enviar uma mensagem)
|
Caro Nelson,
Gostaria de saber se você pode mostrar como ficaram no final do processo os fontes do SERVIDOR e do CLIENTE, pois, implementei aqui e não está enviando as mensagens e/ou se está não está exibindo para os clientes.
Outra coisa, a "Var NumConex : integer; " do trecho abaixo foi criado com qual finalidade?
"procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
Var NumConex : integer;
Begin
IDConexoes.Remove(Socket.Data);
Dispose(Socket.Data);
end; "
O artigo está muito bom,
Aguardo ser retorno.
|
por: yoshinori : Mai 01, 2006 - 09:22 (Informações sobre o membro | Enviar uma mensagem)
|
Alguem conseguiu fazer esta parte:
Function TForm1.LocalizaCliente(Cli : Pointer):Integer;
Begin
Result := IDConexoes.IndexOf(Cli);
End;
Essa parte eu naum consigo implementar não sei aonde eu coloco ???
Por favor prescizo terminar isso urgente...
Agradeço
|
por: edurocha : Ago 09, 2006 - 11:11 (Informações sobre o membro | Enviar uma mensagem) http:// | Esta é uma função criada pelo programador. Você deve substituir o TForm1 pelo nome do seu formulário e colocar function localiza... logo abaixo do texto { Private declarations }
Meu código ficou assim
private
{ Private declarations }
Function LocalizaCliente(Cli: Pointer):Integer;
public
{ Public declarations }
end;
var
frmServidor: TfrmServidor;
IDConexoes: TList;
implementation
{$R *.dfm}
Function TfrmServidor.LocalizaCliente(Cli: Pointer):Integer;
Begin
Result := IDConexoes.IndexOf(Cli);
End;
e funcionando perfeitamente. Parabéns pelo artigo. | [ Comentários não permitidos para usuários anônimos. Por gentileza, registre-se ou conecte-se ao sistema
por: nelsonlima : Dez 10, 2007 - 09:34 (Informações sobre o membro | Enviar uma mensagem) http:// | Cara vc vai ter q amarrar sua conexão em algun dado variavel q vc possa controlar. um exemplo é o nick deste que seja unico. Ai vc localiza no servidor qual conexão está ligado ao nick e o nick dever vir como parametro. O servidor envia então so para quem tiver com o determinado nick. Da um trabalhinho mas da pra fazer. Abraços,
Nelson Lima | [ Comentários não permitidos para usuários anônimos. Por gentileza, registre-se ou conecte-se ao sistema
por: Borghal : Dez 05, 2006 - 05:59 (Informações sobre o membro | Enviar uma mensagem)
http://http://
|
Nelson, essa tua dica é muito boa cara... boa mesmo, com ela eu conseguir fazer um programinha basico pra eu e meus amigos brincarmos de rpg de mesa pela net... bom se alguem quizer o programa, divirtam-se:
http://br.geocities.com/sincos_pcbs/
Grato
Paulo
|
por: macks : Nov 09, 2007 - 06:31 (Informações sobre o membro | Enviar uma mensagem)
|
|
Cara aki copilo blz so q quando vo executa da um erro access violation at adress 00403f09 in module 'batepapo.exe'. read of address 00000000. sabe o q pode ser?
|
por: nathanpc (nathanpc@ymail.com)
: Mai 06, 2009 - 06:06 (Informações sobre o membro | Enviar uma mensagem)
http://
|
Olá,
Alguem poderia me falar se é possível criar este servidor e o cliente para que os meus amigos, lembrando que o meu ip é dinamico, mas eu posso usar o no-ip que eu tenho, por favor me ajudem.
Obrigado,
Nathan Paulino Campos
|
por: neidl (neidantaslopez@gmail.com)
: Nov 13, 2009 - 02:53 (Informações sobre o membro | Enviar uma mensagem)
http://
|
Fiz:
For i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
Serversocket1.Socket.Connections[i].SendText(MsgRecebida);
Mas continua enviando o texto apenas em uma janela... o que será que eu errei?
|
por: Bechir (bechirbitar@hotmail.com)
: Nov 27, 2009 - 04:15 (Informações sobre o membro | Enviar uma mensagem)
http://http://
|
Meu esteu artigo é muito show estava atraz de exemplos para usar Sockets mais nunca encontrei nada com tanta clareza nas explicações mais para ficar Show mesmo teria que ter mais 2 coisinhas que seria derrubar um usuário inconveniente e desligar remotamente um monitor da rede isto é possivel ?
Parabens.
|
por: benkoms (thiagobenko@hotmail.com)
: Out 02, 2012 - 11:27 (Informações sobre o membro | Enviar uma mensagem)
|
Primeiramente gostaria de parabeniza-lo pelo artigo, sem dúvidas está ajudando muita gente (eu me incluo na lista).
Aproveitando da boa vontade dos colegas, eu fiz um aplicativo, não de chat, mas me auxiliar em monitoramento de redes, a questão é:
Teria como eu fazer tipo um scanner, onde eu verificasse se o meu aplicativo está rodando na máquina, se tiver ele me confirma e acrescenta o ip a uma listbox ou coisa assim.
Imaginem vcs uma empresa com 30 computadores vc ter que ficar testando um por um para ver se está rodando ou não.
Quem puder ajudar, me mande um e-mail: thiago@concepttecnologia.com
|
|
|
Edição 112 |
|
|
50 Programas Fontes |
|
|
Produtos |
|
|