Este artigo é o primeiro de uma série de três.
Olá a todos, bem-vindos ao primeiro artigo da série de tutoriais da nim-libp2p!
Este tutorial é para todos que estão interessados em construir aplicativos de chat ponto a ponto. Nenhuma experiência de programação em Nim é necessária.
Para dar uma visão geral rápida, Nim é a linguagem de programação que estamos usando e nim-libp2p é a implementação Nim de libp2p, uma biblioteca modular que permite o desenvolvimento de aplicativos de rede ponto a ponto.
Hoje vamos orientá-lo através de um exemplo de chat ponto a ponto. O código completo pode ser encontrado em nosso repositório principal directchat.nim. O código para esta parte está em start.nim.
Espero que seja útil em sua jornada de aprendizado. Boa programação! ;)
Nota: Este tutorial está dividido em três partes conforme abaixo:
- Parte I (agora): Configure a função principal e use multi-thread para processar entrada e saída.
- Parte II: Discar ponto remoto e permitir comandos de entrada personalizados para usuários.
- Parte III: Configurar e estabelecer um nó libp2p.
Antes que você comece
O único pré-requisito aqui é o Nim, a linguagem de programação com uma sintaxe semelhante ao Python e um desempenho semelhante ao C. Informações detalhadas podem ser encontradas aqui.
- Instale o Nim através do site oficial: https://nim-lang.org/install.html
- Verifique a instalação do Nim via
nim --version
e seu gerenciador de pacotes Nimble vianimble --version
.
Executando o Exemplo
Primeiro, abra seu terminal e clone o repositório git que contém nosso código de exemplo.
git clone https://github.com/status-im/nim-libp2p.git
Em seguida, instale as dependências.
cd nim-libp2p
nimble install
Navegue até a pasta de exemplos.
cd examples
Tente compilar e executar o código para ter certeza de que tudo está funcionando.
nim c -r --threads:on directchat.nim
# Isto equivale a: nim compile --run --threads:on directchat.nim
# --threads:on significa ativar o suporte para multi-threading
Você está pronto para prosseguir se vir a seguinte saída:
Saída do terminal após executar directchat.nim
Comece a codificar!
Nesta seção, passaremos pelo código linha por linha, começando do básico. Sinta-se à vontade para pular se você já for muito experiente em Nim.
Configure o procedimento principal
Vamos primeiro criar uma função (chamada procedure em Nim) que imprime uma string "hi"!
- Crie um novo arquivo chamado
start.nim
no diretóriotutorial
- Copie e cole o seguinte código em nosso novo arquivo.
import chronos
proc main() {.async.} =
echo "hi"
when isMainModule:
waitFor(main())
A primeira linha importa o módulo " chronos ", que é uma biblioteca eficiente para programação assíncrona. Desenvolvido pela Status, o chronos começou como uma bifurcação da biblioteca padrão Nim async, mas desde então divergiu significativamente. Você pode encontrar mais documentação, notas e exemplos em seu Wiki.
Então, a palavra chave proc
define nosso procedimento principal com o nome main
. A sintaxe {. .}
é chamada pragma em Nim. A palavra-chave async
nele diz ao compilador para habilitar os recursos assíncronos para nosso procedimento.
A parte final deste código espera que nosso procedimento principal assíncrono seja executado pela palavra chave waitFor
. Na penúltima linha há uma constante especial isMainModule
, que será true
quando este módulo for compilado como arquivo principal.
- Tente executar o trecho acima digitando-o no terminal. Você deve ver "hi" sendo impresso.
cd ../tutorial
nim c -r start.nim
Saída do terminal após executar start.nim
Ler e processar a entrada do console
Neste exemplo, esperamos processar nossos procedimentos enquanto acessamos a entrada do usuário. Para conseguir isso, usaremos multi-threading.
Primeiro, crie um procedimento para acessar a entrada do usuário.
proc readInput(wfd: AsyncFD) {.thread.} =
## Este procedimento realiza a leitura de `stdin` e envia dados
## linha para a thread principal.
let transp = fromPipe(wfd)
while true:
let line = stdin.readLine()
discard waitFor transp.write(line & "\r\n")
Neste procedimento, usamos while true
para acessar continuamente a entrada do usuário de stdin e gravar o resultado em nosso descritor de arquivo de gravação wfd
. A entrada será então encaminhada para rfd
ser processada posteriormente.
Criar outro procedimento para imprimir a entrada.
proc processInput(rfd: AsyncFD) {.async.} =
echo "Type something below to see if the multithread IO works:\nType 'exit' to exit."
let transp = fromPipe(rfd)
while true:
let a = await transp.readLine()
if a == "exit":
quit(0);
echo "You just entered: " & a
Leia mais sobre o que é pipe, stdin, stdout e descritor de arquivo neste blog. Em resumo, o pipe é para conectar a entrada e a saída padrão aqui.
Aqui você pode ver que quando o usuário digita "exit", o programa finaliza com quit(0)
onde 0 significa sair sem erros.
Em seguida, edite nosso procedimento principal para criar um conexão para enviar dados entre diferentes threads e atribuir seu manipulador à nova instância com base em nosso objeto.
proc main() {.async.} =
let (rfd, wfd) = createAsyncPipe()
if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe:
raise newException(ValueError, "Could not initialize pipe!")
var thread: Thread[AsyncFD]
thread.createThread(readInput, wfd)
await processInput(rfd)
Na primeira parte do código, rfd
significa ler descritor de arquivo e wfd
significa gravar descritor de arquivo. createAsyncPipe
configura e retorna um conexão assíncrona que encaminha os dados gravados em wfd
para serem lidos no rfd
. Exceções são geradas se o valor de retorno for inválido.
A parte restante é autoexplicativa. Criamos uma thread para acessar continuamente a entrada do usuário e, em seguida, processar nossos dados de entrada.
Outra coisa a observar é que usamos var
em vez de palavra chave let
ao declarar thread
porque let
requer inicialização e o valor não pode ser alterado uma vez atribuído. Nós apenas especificamos o tipo de thread
mas não damos o valor inicial aqui.
Por fim, lembro nosso usuário de adicionar a opção threads:on
de multi-threading ao executar nosso script. Adicione esta linha antes de nossa instrução de importação.
when not(compileOption("threads")):
{.fatal: "Please, compile this program with the --threads:on option!".}
Execute start.nim
e veja se seu input/output funciona bem. Lembre-se de adicionar threads:on
aqui, pois estamos usando multi-thread.
nim c -r --threads:on start.nim
- Saída do terminal após executar start.nim.
Conclusão
Agora você aprendeu a sintaxe básica do Nim e tem um script totalmente funcional para usar multi-threading facilmente para processar entrada e saída.
No próximo tutorial, veremos como chamar um ponto remoto e permitir que o usuário insira comandos personalizados. Fique ligado!
Este artigo foi publicado por Lee Ting Ting e traduzido por Marcelo Panegali. Seu original em inglês pode ser encontrado aqui.
Latest comments (0)