Uso do Node para Comunicação TCP ou UDP

564 views
Skip to first unread message

Filipe Sguarizi Panceri

unread,
Jun 3, 2015, 12:18:56 PM6/3/15
to nod...@googlegroups.com
Senhores,
   até ja li algo sobre isso na lista de discussão, mas o fato é que ainda não me convenci. Estou para iniciar um projeto que basicamente vai se comunicar com alguns equipamentos. Vou receber várias mensagens desses equipamentos, em um protocolo específico e vou precisar armazenar em banco. Pelo fato do node ser single thread não terei problemas de concorrência? Se alguém tiver algum material específico sobre o assunto ajudaria.

Att,
Filipe Sguarizi Panceri

Marcos Bérgamo

unread,
Jun 3, 2015, 12:23:23 PM6/3/15
to nod...@googlegroups.com
Olá Felipe!

No final do ano passado fiz uma aplicação usando um socket TCP para a comunicação entre uma api web e meus alguns hardwares. Minha concorrência foi de apenas 5 no máximo, entretanto a questão de ser single thread não influência em nada no caso do node a concorrência.

Uma vez que o event loop trata as requisições você não precisa se preocupar em perder requisições, pois tudo vai entrar na fila do event loop para ser executado. 

[]s

--
Você recebeu essa mensagem porque está inscrito no grupo "Node.js Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para nodebr+un...@googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.

principe...@gmail.com

unread,
Jun 3, 2015, 12:23:52 PM6/3/15
to nod...@googlegroups.com
para concorrencia vc pode usar o modulo cluster....vc pode pesquisar tb sobre modulos no npm, por exemplo la tem modulo para serial, onde eu utilizei para comunicar com arduino que utiliza o protocolo rs232 (serial), nao sei quais protocolos seus equipamentos utilizam, mas vc pode dar uma pesquisada...

--

Filipe Sguarizi Panceri

unread,
Jun 3, 2015, 12:28:04 PM6/3/15
to nod...@googlegroups.com
Vai ser um protocolo proprietário, vou ter que implementar a "deserialização" da mensagem, e se não for TCP, provavelmente vou precisar enviar um ACK para o equipamento. Não vi o protocolo ainda, mas provavelmente algo com tamanho fixo e talz...

Filipe Sguarizi Panceri

Alan Hoffmeister

unread,
Jun 3, 2015, 12:38:03 PM6/3/15
to nod...@googlegroups.com
Filipe, no meu trabalho utilizo Node.js para comunicação serial e TCP, também precisei implementar um protocolo na mão e a API de buffers do Node.js é excelente para isso, tem praticamente tudo o que vc vai precisar para escovar bits. A ferramenta também ficou bem performática, no meu caso os frames são curtos e o parse não é nada demorado, mas não recomendo fazer o parse de algum binário enorme com JavaScript pois fica bem lento, recomendo criar uma extensão em C/C++, Go ou Rust para isso, o node consegue se integrar bem à essas linguagens.

Filipe Sguarizi Panceri

unread,
Jun 3, 2015, 12:40:55 PM6/3/15
to nod...@googlegroups.com
Ola Alan, não tenho os detalhes ainda, mas acredito que os frames serão curtos. A idéia é recebe o pacote, deserializa, grava na base. Depndendo do pacote e do protocolo utilizado irá retornar um ack de aplicação. Mas é só isso...

Filipe Sguarizi Panceri

Alan Hoffmeister

unread,
Jun 3, 2015, 12:42:18 PM6/3/15
to nod...@googlegroups.com
Fácil, não vai ter problemas, se encontrar alguma dúvida posta aqui no grupo que eu te ajudo :-)

Filipe Sguarizi Panceri

unread,
Jun 3, 2015, 12:46:48 PM6/3/15
to nod...@googlegroups.com
Obrigado pelo apoio pessoal, só mais uma pergunta. Posso usar essa mesma aplicação para servir páginas WEB? A idéia é que tenha um portal para que se possa consultar as informações sobre os equipamentos. Ou seria melhor implementar outra aplicação para isso??


Att,

Filipe Sguarizi Panceri

Alan Hoffmeister

unread,
Jun 3, 2015, 12:57:28 PM6/3/15
to nod...@googlegroups.com
No seu caso eu estaria inclinado a utilizar um outro processo/aplicação para isso, vocês possuem um ponto em comum que é o banco de dados, logo uma parte não depende da saúde da outra (tcp / webserver) para funcionar corretamente. Talvez um approach ainda melhor seria uma estrutura de micro serviços.

Marc Pires

unread,
Jun 3, 2015, 1:38:32 PM6/3/15
to nod...@googlegroups.com
Em caso de querer partir para a arquitetura de microserviços, uma leitura interessante é http://martinfowler.com/bliki/MicroservicePrerequisites.html

Alain Mouette

unread,
Jun 3, 2015, 3:49:52 PM6/3/15
to nod...@googlegroups.com
Acho que o quele precisa é entender como que a operação assíncrona do Node evita esses problemas...
Onde tem uma boa explicação para isso?
Alguém sabe?

Aliás, vejo muito na lista em inglês discussões sobre exatamente esse assunto...

RESPOSTA CURTA: Em node.js você vai ter menos problemas e poder atender muito mais conexões!

Alain Mouette
=== Projetos especiais: <http://lnkd.in/dEu8cNq> ===

Alan Hoffmeister

unread,
Jun 3, 2015, 4:25:43 PM6/3/15
to nod...@googlegroups.com
Na verdade aprender programação assíncrona quer dizer que você precisa reajustar o seu cérebro para pensar em programação orientada a eventos: como chamar um evento, como esperar um evento, como capturar erros de um evento, etc..

Não falei sobre isso pois ele não comentou que era iniciante :P

David Lojudice Sobrinho

unread,
Jun 4, 2015, 9:17:43 AM6/4/15
to nod...@googlegroups.com
Filipe,

Tenho um pet project que é a implementação do Memcached server em Javascript / Node.js:


Ali vc vai ter um exemplo de como usar o socket TCP. Pode inclusive comparar um protocolo ASCII, com parser e um protocolo binário, com tamanhos fixos (bem mais performático).

Abs,

David

Filipe Sguarizi Panceri

unread,
Jun 10, 2015, 2:57:34 PM6/10/15
to nod...@googlegroups.com
Reaproveitando a Thread. Tive mais informações sobre o projeto e quero garantir que não vou passar sufocos.
O projeto continua o mesmo, mas em determinados casos, vou precisar mandar comandos para o equipamento, provavelmente quando ele se comunicar com o server, tenho que buscar se existe algum comando pra esse cara e enviar. Aqui cabem algumas dúvidas e considerações:

 - Ao chegar uma mensagem, vou deserializar (protocolo proprietário simples) e gravar na base. (Pretendo usar a api rest da aplicação WEB para isso, é valido?).
 - Quando recebo essa mensagem, preciso verificar se existe algum comando para mandar para esse equipamento. Isso pode ser demorado, devo fazer isso de forma assíncrona ou crio workers para tratar isso ou outra coisa??

Sou do mundo Java, e quero sair da zona de conforto. Se fosse pra fazer em java, criaria uma thread para cada nova conexão e não teria problemas em demorar em todos esses processos.

Att,

Filipe Sguarizi Panceri

--

Pineli

unread,
Jun 11, 2015, 9:58:12 PM6/11/15
to nod...@googlegroups.com
Ola Felipe, 

Já desenvolvi algumas aplicações embarcados e passei por algumas situações parecidas, mas acabei usando sockets. Você disse que vai usar conexão TCP ou UDP, nestas duas opções você está se referindo a socket ou http mesmo?

Com socket, depois que abrir o canal não tem segredo, vira um chat. Só manter o heartbeat, se precisar reconectar. 

Em http (rest) dependendo da aplicação fica mais complexo. Desta forma nunca o servidor poderá enviar a informação para o dispositivo, no momento que acontecer (dependendo da aplicação), a não ser quando ele faz uma requisição dai você aproveita o retorno, como você citou. Em um caso meu, tudo era muito rápido então não tive problemas e a api rest funcionou perfeitamente. 

Você disse que pode ser demorado ai talvez tenha um problema de timeout no dispositivo, teria que testar. Na minha opinião com certeza deve fazer assíncrono no server para ganhar performance mas mesmo assim a resposta vai demorar devido ao seu processamento e você vai ter que garantir a conexão do lado do dispositivo. 

Falando besteira rsrs, talvez poderia fazer a api notificar o dispositivo quando estiver pronto o processamento, desta forma o dispositivo também deveria estar pronto para receber requisições. Para saber onde esta o dispositivo, poderia pegar seu ip no momento do ultimo request.

abç

Filipe Sguarizi Panceri

unread,
Jun 12, 2015, 8:15:39 AM6/12/15
to nod...@googlegroups.com
Obrigado pela resposta Pinel.

Quando falo TCP/UDP é socket mesmo. Protocolo nem vai ser binário, vai ser ASCII mesmo. Quanto ao processamento assíncrono eu não sei se rola, pela parte do equipamento. O equipamento esta sendo fabricado na China e ja vou receber ele pronto. Nem maiores informações de troca de mensagens eu tenho mas ja trabalhei bastante com isso em java. Andei pensando na arquitetura e imaginei o seguinte:
Os comandos que deverão ser enviados ao equipamento, serão cadastrados na minha interface web, sendo assim após gravar na base de dados, eu poderia mandar para o aplicativo que se comunica com os equipamentos, via algum serviço de mensageria (0mq, Rabbit ou qualquer outra coisa). Dessa forma no lado do parser, eu poderia manter essas mensagens em um Redis da vida, para que quando o equipamento de sinal de vida, eu pego as mensagens que tem pra ele no Redis e envio. Mas como não conheço muito de node ainda, tenho um certo receio, ja que teoricamente a aplicação ficaria bloqueada enquanto faço o que tenho que fazer com o equipamento. Poderia ter algum esquema de workers, para tratar cada conexão?

Desculpem estar jogando todo o meu problema aqui pra vocês, mas é que realmente tenho muitas dúvidas e não consegui sanar apenas com buscas pela internet.

Att,

Filipe Sguarizi Panceri

Pineli

unread,
Jun 15, 2015, 4:33:20 PM6/15/15
to nod...@googlegroups.com
Entendi, 

Você poderia criar metodos assincronos para fazer este processamento que você acha demorado. 

Pode usar o child process que abre um novo workr ou fazer um metodo com process.nextTick ou tbm o setTimeout (particularmente são as formas que conheço). 

Gustavo Duarte

unread,
Jun 15, 2015, 5:08:09 PM6/15/15
to nod...@googlegroups.com
Filipe,

Esses dois trechos me chamaram a atenção:


"Quando recebo essa mensagem, preciso verificar se existe algum comando para mandar para esse equipamento. Isso pode ser demorado, devo fazer isso de forma assíncrona ou crio workers para tratar isso ou outra coisa??"

"Mas como não conheço muito de node ainda, tenho um certo receio, ja que teoricamente a aplicação ficaria bloqueada enquanto faço o que tenho que fazer com o equipamento. Poderia ter algum esquema de workers, para tratar cada conexão?"

Acho que pode haver um erro sutil nessa análise. O event loop do Node só fica bloqueado se o seu código *não* está fazendo system calls como write(), send(), connect(), etc. Ou seja, basicamente se você está em algum tipo de busy loop, usando a CPU de alguma maneira mas sem nunca usar funções de IO. Mas se você está mandando e recebendo mensagens para o equipamento via TCP/IP, não é necessário bloquear o event loop enquanto você espera uma resposta do equipamento. Mesmo que a interação total leve tempo, cada passo é executado muito rapidamente via event loop do Node, e a alegria reina no mundo.

Se de fato você precisar ficar em um busy loop por algum motivo de hardware - por exemplo, as vezes drivers do kernel fazem isso devido à algum timing requirement do hardware, ou as vezes é necessário adquirir uma spin lock, etc. - ai de fato isso pode ser um problema no event loop padrão. Mas isso geralmente só é o caso para drivers mesmo, quando estamos comunicando via I/O ports, DMA, etc.

Me parece que não é esse o caso, e que você pode usar Node de maneira padrão e ser feliz. Se você de fato precisasse usar workers, imagino que o melhor tradeoff seria usar subprocessos.

Você chegou a escrever alguma app pequena em Node? Caso você não o tenha feito ainda, imagino que uma app simples vai te dar um entendimento intuitivo de como o assincronismo funciona no Node. Tipo algo que faça um readdir() recursivo, ou que faça download de uma página via HTTP, ou leia uns arquivos, etc.

Boa sorte!

Filipe Sguarizi Panceri

unread,
Jun 16, 2015, 7:50:16 AM6/16/15
to nod...@googlegroups.com
Olá Gustavo, ja brinquei com pequenas coisas em node. O clássico servidorzinho web, e dei manutenção em outra aplicação web também. Mas vamos la, vou tentar esboçar um cenário aqui em palavras e depois faço os questionamentos:

Cenário 1

Equipamento A manda uma mensagem para minha aplicação. Eu recebo essa mensagem, deserializo (coisa simples, protocolo ASCII com mencionei aintes), caso tenha algum problema com a mensagem, mando um NACK para o equipamento que vai me mandar a mensagem novamente. Seguimos em frente, a mensagem que eu recebi estava OK eu salvo ela no banco de dados e faço uma consulta para saber se existe algum comando para enviar para o equipamento. Existe, eu trago esse comando da base, serializo, mando para o equipamento e aguardo o retorno (tudo isso tem que ser síncrono a princípio), esse retorno vou salvar no banco de dados e pronto, terminei de interagir com esse equipamento por hora. Agora vamos as dúvidas:

1 - O que acontece enquanto eu estou em comunicação com esse equipamento e outro equipamento resolve se comunicar? Pelo que entendo isso vai entrar na "fila" do event loop, e assim que eu concluir todas essa interação com o equipamento ele vai ser processado certo?

2 - Quem ja trabalhou ou apenas conhece um pouco de protocolos de comunicação sabe que uma escrita na pilha TCP de um lado, não resulta efetivamente em apenas uma leitura do outro lado certo? Dessa forma não vai ser apenas em um "onData" do socket que eu vou conseguir ler todos os dados dessa mensagem. Quando trabalho com isso em java, uso threads e não tenho problemas quanto a isso ja que leio uma quantidade X de dados e aloco em um buffer, enquanto outra rotina vai consumindo e processando esses dados (por thread ou seja por equipamento). Agora no node acho que não funciona dessa forma. Teria que "travar" o socket para que enquanto não chegar toda mensagem do equipamento X o equipamento Y não teria sua mensagem recebida. Apenas um detalhe, a comunicação dos equipamentos provavelmente será via GPRS, ou seja, a velocidade é uma tragédia...

3 - Pior cenário do mundo, todos os 2000 equipamentos saem do ar e voltam ao mesmo tempo. E olha que isso não é tão difícil de acontecer, terei 2000 vezes o cenário 1 ali de cima enfileirado, certo??

Talvez para entender efetivamente como o node se comporta, penso em uma aplicação que recebe um upload de imagens. Mas vamos imaginar imagens grandes, enquanto estou recebendo a imagem 1 o que acontece com a imagem 2? Timeout? Outra abordagem?


Acho que é isso pessoal.

Att,

Filipe Sguarizi Panceri

Racz

unread,
Jun 16, 2015, 8:39:39 AM6/16/15
to nod...@googlegroups.com
Filipe,

Na prática, o node usa Threads para comunicação, somente essas threads não ficam visíveis para o usuário. O tempo que fica bloqueado é apenas o tempo que o código Javascript executa, então pode exemplo no seguinte código:

socket.on('data', function(data) {
console.log('Received: ' + data);
socket.write('Resposta');
});

Seu código só bloqueia por alguns milissegundos, durante a execução do método. 
A chamada ao write também ocorre sem bloquear o event loop.


Para ter o benefício do node, você tem que abraçar a idéia de ser assíncrono, não dá pra lutar contra ela. Para usar o node, você tem rever essa frase que disse: "(tudo isso tem que ser síncrono a princípio)".

Na realidade não tem que ser síncrono, você pode armazenar o estado atual e criar handlers específicos para cada caso, todos assíncronos.

Então como exemplo,  o seu cenário ficaria assim (fiz numerando as operação e escrevi um pseudo código pra dar pra entender melhor).

1 - Equipamento A manda uma mensagem para minha aplicação. Eu recebo essa mensagem, 
2 - Deserializo (operação síncrona)
3 - Caso tenha algum problema com a mensagem, mando um NACK para o equipamento (operação assíncrona) 
1 - que vai me mandar a mensagem novamente (operação assíncrona, na verdade, ele pode voltar pro começo) - volta pra 1 de novo  
4 - Seguimos em frente, a mensagem que eu recebi estava OK eu salvo ela no banco de dados (operação assíncrona)
5 -  e faço uma consulta para saber se existe algum comando para enviar para o equipamento. (operação assíncrona)
6 -  Existe, eu trago esse comando da base, (operação assíncrona)
7 -  serializo, (operação síncrona)
8 -  mando para o equipamento (operação assíncrona) e 
9 - aguardo o retorno (operação assíncrona), - VOLTA PRA 1
10 - esse retorno vou salvar no banco de dados (operação assíncrona) 
11 - e pronto, terminei de interagir com esse equipamento por hora. 
  
  
Exemplificado em pseudo código:
//1
socket.on('data', function(data) {
//2
var mensagem = deserializar(data);
if (!isOk(mensagem)) {
//3
socket.write('NACK');
} else {
if (mensagem.tipo == 'RETORNO_COMANDO') {
// 9 - Recebi retorno do último comando
// 10 - salva retorno (assíncrona)
banco.save(mensagem, function(result) {
//11 - manda resposta
socket.write('OK');
});
} else {
// 4 , essa chamada é assíncrona
banco.save(mensagem, function(result) {
// 5 - novamente assíncrona
banco.trazerComando(mensagem.id_equipamento, function(comando) {
if (comando != null) {
//7
var dataToSend = serializar(comando)
// 8 - Assincrono de novo
socket.write(dataToSend);
} else {
//11 - manda resposta
socket.write('OK');
}
});
}
}
}
});


Resumindo o código que bloqueia o event loop é praticamente só a serialização e deserialização das mensagens (e mesmo esse, daria pra fazer de forma assíncrona em C se você achar que dá gargalo).

Espero que tenha sido claro o exemplo. Qualquer dúvida, estamos aí,

Att,
Rácz


Filipe Sguarizi Panceri

unread,
Jun 16, 2015, 8:47:08 AM6/16/15
to nod...@googlegroups.com
Você é o cara Racz rsrsrs, agora você me convenceu 90%. Neste exemplo estamos partindo do pressuposto que a mensagem chegou inteira no onData. Caso eu receba a mensagem pela metade, eu teria que acumular isso em um buffer ou algo assim, e ir "encontrando" as mensagens certo? Não sei se fui claro...

Filipe Sguarizi Panceri

Pineli

unread,
Jun 16, 2015, 9:03:02 AM6/16/15
to nod...@googlegroups.com
Felipe,

Conforme a explicação do Racz,  você não tem que esperar a resposta, simplesmente deixa ela chagar. 

sobre pegar a mensagem inteira, poderia ser algo assim não testei:

var data = ''

socket.on('data', function(chunk) {
  data += chunk;
});

socket.on('end', function() {

   var mensagem = deserializar(data);

});



Em 16 de junho de 2015 09:39, Racz <andre...@gmail.com> escreveu:

Racz

unread,
Jun 16, 2015, 9:05:43 AM6/16/15
to nod...@googlegroups.com
Filipe,

Disponha! qualquer dúvida estamos aí.
 
Para tratar  mensagens parciais teria que fazer algo desse tipo. Ou achar algum pacote que faça isso por você.


Abraço,
Racz


Filipe Sguarizi Panceri

unread,
Jun 16, 2015, 9:09:21 AM6/16/15
to nod...@googlegroups.com
Valew pessoal, assim que tiver algo mais consistente (receber o ok para iniciar o projeto, receber equipamentos) eu procuro uma forma de postar como foi o desenvolvimento dessa solução.


Att,

Filipe Sguarizi Panceri
Reply all
Reply to author
Forward
0 new messages