Read-all echo TCP server

I need to write a Julia server that reads the entire message coming from a client, and then sends a reply back. However, it seems that when the message is read, the socket gets closed, so I can’t write the reply.

Server code:

using Sockets

port = 5678
server = listen(port)
sock = accept(server)

while isopen(sock)
  m = read(sock, String)
  write(sock, m)
end

Client:

$ cat input.txt | nc localhost 5678

On write, the server raises the error “IOError stream is closed or unusable”.

Is there a way to make sock not close too soon?

Not sure why you are getting this error, but the examples in the manual is as follows. Maybe that keep=true option is important?

julia> @async begin
           server = listen(2001)
           while true
               sock = accept(server)
               @async while isopen(sock)
                   write(sock, readline(sock, keep=true))
               end
           end
       end
Task (runnable) @0x00007fd31dc12e60

julia> clientside = connect(2001)
TCPSocket(RawFD(28) open, 0 bytes waiting)

julia> @async while isopen(clientside)
           write(stdout, readline(clientside, keep=true))
       end
Task (runnable) @0x00007fd31dc11870

julia> println(clientside,"Hello World from the Echo Server")
Hello World from the Echo Server

The server indeed works with a client like that, but doesn’t work with my netcat client, which provides limited input stream to the server.

The keep parameter is for keeping end-of-line symbols if I am not mistaken.

I think the issue is with netcat. See this stack exchange question:

I am not sure :frowning: The problem seems to be in that Julia’s socket becomes closed in both directions after netcat closes just one side. After one read, sock becomes unusable and does not let to write into it.

That certainly sounds like a bug, I would recommend filing an issue on the Julia issue tracker with your MWE.

1 Like

Thanks, I will. The socket becomes closed after any call to read

Out of curiosity, are you using it in a scripting environment (Atom, VSCode, Jupyter/Pluto notebooks) or running it as a script?

I had an issue like this a few years back when I tried to run code similar to this in a dynamic setting, but when it was ran as a script it somehow all worked just fine.

Running as a script.

I have a program that reads stuff from IO till EOF and produces the result. And I’d like to simply turn this program into a simple server, smth like

server = listen(port)
sock = accept(server)

main(in::IO, out::IO) = ...
main(sock, sock)

close(sock)
1 Like