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 --versione 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.nimno 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.
            

          
          
    
Top comments (0)