.png)
Meu objetivo é criar um servidor de eco simples usando nc
um único arquivo fifo
. Não estou procurando a melhor maneira de fazer isso, estou apenas tentando entender a semântica dos comandos a seguir (quando acontece o fork, por que, o que muda, por que os comandos se comportam de maneira diferente...).
Estou usando o Bash, então não tenho certeza se todos os comandos funcionarão com POSIX sh
ou zsh
, ksh
, ...
Aqui estão os quatro comandos que menciono no título (supondo que já os tenha feito mkfifo fifo
):
cat fifo | nc -l localhost 8888 > fifo
exec 3<> fifo && nc -l localhost 8888 <&3 >&3 && exec 3>&-
nc -l localhost 8888 <(cat fifo) > fifo
nc -l localhost 8888 < fifo > fifo
Agora eu esperaria que os 4 comandos fizessem a mesma coisa, pelo menos os dois últimos fizessem a mesma coisa.
- O primeiro comando se comporta conforme o esperado, um servidor de eco simples que é encerrado quando o cliente encerra a conexão.
- Comporta-se como 1.
- Posso me conectar ao servidor, enviar dados, mas nunca recebo nada de volta. Quando fecho a conexão do cliente, o servidor é desligado.
- Não é possível conectar-se ao servidor, o servidor escuta para sempre.
Responder1
A chave aqui é que abrir um FIFO é uma operação de bloqueio. O open
único retorna quando ambas as extremidades estiverem conectadas, ou seja, quando o fifo estiver aberto tanto para leitura quanto para escrita.
Normally, opening the FIFO blocks until the other end is opened also.
No 1º caso, o shell se bifurca para executar o pipeline, portanto a abertura do fifo para leitura ( cat fifo
) e a abertura do fifo para gravação ( > fifo
) acontecem em processos separados, portanto acontecem de forma independente.
No 2º caso, a abertura para leitura e a abertura para escrita ( 3<>fifo
) acontecem em uma única etapa.
No terceiro caso, <(cat fifo)
expande para um nome de arquivo, por exemplo /dev/fd/42
, . Então é como se você estivesse correndo nc -l localhost 8888 /dev/fd/42 > fifo
. Você precisa de um extra <
para que seja equivalente, por exemplo nc -l localhost 8888 < <(cat fifo) > fifo
.
No 4º caso, o shell está tentando abrir o fifo para leitura ( < fifo
) e abri-lo para escrita ( > fifo
) como parte do mesmo processo. O shell faz um de cada vez, da esquerda para a direita. Então ele tenta abrir fifo
para leitura e bloqueia para sempre, esperando que algo abra fifo
para escrever. Acho que você descobrirá que, neste caso, nc
nem sequer comecei e a porta nunca foi aberta para escuta.