# Using Julia Sockets to send message to an existing TCP Socket

**URL:** <https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191>\
**Category:** New to Julia\
**Tags:** question, sockets\
**Created:** [February 10, 2022, 7:51pm UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191 "2022-02-10T19:51:37Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![hanshinlee77](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hanshinlee77/32/32867_2.png) [@hanshinlee77](https://discourse.julialang.org/u/hanshinlee77)\
**Post date:** [February 10, 2022, 7:51pm UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/1 "2022-02-10T19:51:37Z")

</div>

Hi, I have a problem to send a simple message to an existing TCP server, using Julia Sockets module.

I used one of the “C” examples on the web to test if I can make a connection and send/receive messages to/from the server. This works fine. This C code (called client\_c.c) is below:

```julia
#include<stdio.h> //printf
#include<string.h> //strlen
#include <unistd.h>
#include<sys/socket.h> //socket
#include<arpa/inet.h> //inet_addr

int main(int argc , char *argv[])
{
    int sock;
    int proto = 6; // TCP protocol
    struct sockaddr_in server;
    char message[100] , server_reply[1024];

    //Create socket
    sock = socket(PF_INET , SOCK_STREAM , IPPROTO_TCP);

    if (sock == -1)
    {
        printf("Could not create socket");
    }
    puts("Socket created");

    server.sin_addr.s_addr = inet_addr("198.214.229.46");
    server.sin_family = AF_INET;
    server.sin_port = htons( 22401 );

    //Connect to remote server
    if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
    {
        perror("connect failed. Error");
        return 1;
    }

    puts("Connected\n");
    memcpy(message,"iraf", 4);

    if ( send(sock,message,100,0) < 0 )
    {
        puts("Failed to send message");
        return 1;
    }

    if ( recv(sock, server_reply, 1024, 0) < 0 )
    {
        puts("Failed to receive message");
    }
    printf("%s\n",server_reply);

    close(sock);
    return 0;
}

```

After compiled to an executable called client\_c and upon running it results in the following:

```julia
shell> ../../client_c
Socket created
Connected

  2 6 Thu Feb 10 2022( 41) 18:15:35.1 0 0 0
 LST/HA +20:42:42.34 - 0: 0: 0.37 180.0 50.8 1.5792
 MEAN +20:41:28.96 -20:11:12.6 2000.0 0.000 0.00
 APP +20:42:42.99 -20: 6:36.9 2022.1
 REFRA +20:42:42.71 -19:59:55.8 2022.1
 RAW +20:42:42.71 -19:59:55.8 2022.1
 107 F 36974

```

The last 7 rows are the messages from this TCP server.

Now, I tried to do the same thing in Julia by the following:  
(Please note that I am pretty new to this).

```julia
# Import Sockets module
using Sockets

# Establish socket connection to the TCP server
tcs = connect(TCPSockets(;delay=false), IPv4("192.214.229.46"), 22401)

# Create 100 byte Char array with command "iraf"
a = Array{Char,1}(undef,100)
a[1:4] = collect("iraf")

# Write the message to the socket
write(tcs,String(a))

# Read message back from the server
read(tcs)

close(tcs)

```

Please note that the TCP server expects a message from a client to be 100 byte long string and that is why I created char array “a” of length 100, put the message, and converting it to String when writing it to the socket.

When running this in REPL, write(tcs,String(a)) return 100 which is the length of the message, but it hangs at read(tcs) line. Upon re running it up to write(tcs,String(a)), I saw tcs having no bytes. I am supposing that this is why read() hangs, but not sure whether the way I am connecting to the server in Julia is identical to that in client\_c.c (?).

Also note that this TCP server is quite old and is a complete black box…

I really wish experts can give a pointer to a possible resolution.  
I appreciate any help.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 11, 2022, 1:43am UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/2 "2022-02-11T01:43:37Z")

</div>

> [@hanshinlee77](#):
>
> `a = Array{Char,1}(undef,100)`

The fact that this is `undef` looks like a problem. The 100 `Char`s in this array could be anything which happens to be in memory (except for the first four set to `"iraf"`). This same bug occurs in the C code, but you might just be lucky there and the rest of the buffer might be set to zeros.

Note also that `Char` is any Unicode character, so is 32 bits in size. `String(a)` will construct a UTF-8 encoded string from that, which might happen to be 100 bytes long, but it could be longer. This is probably not what you want! Instead I’d try

```julia
buf = zeros(UInt8, 100)
buf[1:4] = codeunits("iraf") # works because "iraf" is ASCII, so there's one byte per char here in codeunits.

write(tcs, buf)

```

This might not fix the problem, but it’ll be a step in the right direction.

---

<div class="post-metadata">

**Author:** ![hanshinlee77](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hanshinlee77/32/32867_2.png) [@hanshinlee77](https://discourse.julialang.org/u/hanshinlee77)\
**Post date:** [February 11, 2022, 7:05pm UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/3 "2022-02-11T19:05:28Z")

</div>

Hello Chris, Thank you for pointing out this.  
I tried it but without success unfortunately.

Out of curiosity, I used one of Python examples from the web.

The code is as follows:

```julia
import socket

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect the socket to the port where the server is listening
server_address = ('198.214.229.46', 22401)
print ('connecting to %s port %s' % server_address)
sock.connect(server_address)

try:
    
    # Send data
    message = 'iraf '
    print ('sending "%s"' % message)
    sock.sendall(message.encode('ascii'))

    # Look for the response
    amount_received = 0
    amount_expected = len(message)
    
    
    data = sock.recv(1024)
    print ('received "%s"' % data)

finally:
    print ('closing socket')
    sock.close()

```

Note that message is 100 in length (bytes?) and gets encoded in ascii in sendall() method, but it worked the same even if it was encoded in the default ‘utf-8’. ‘utf-16’ didn’t work.  
Upon running it, I get the expected response (like in the c example) back from the server as follows:

```julia
[lee@atlas2 test]$ python test2tcs.py
connecting to 198.214.229.46 port 22401
sending "iraf "
received " 2 6 Fri Feb 11 2022( 42) 18:40:41.9 0 0 0
 LST/HA +21:11:49.83 - 0: 0: 0.28 180.0 50.8 1.5792
 MEAN +21:10:37.96 -20:11:54.3 2000.0 0.000 0.00
 APP +21:11:51.06 -20: 6:39.0 2022.1
 REFRA +21:11:50.10 -19:59:57.8 2022.1
 RAW +21:11:50.10 -19:59:57.8 2022.1
 107 F 36616
"
closing socket

```

Note that Python 2.6.6 was used to run this.

For a novice like me, the only difference of the Julia script that I can tell from the C / Python codes is the way the TCP/IP socket is defined at the beginning. In both C and Python examples, the socket gets defined with parameter such as AF\_INET and SOCK\_STREAM. Changing SOCK\_STREAM to SOCK\_DGRAM resulted in connection refused. So, the server seems clearly operating in STREAM mode. It is unclear to me how Julia Sockets creates a TCP Socket when issuing connect() method. At least I could not find information how this is set up in Sockets.jl documentation.

I suppose I could write what I need in C and call it from Julia to get around this problem, but it seems like I am missing some basic thing in using Sockets.jl to do this.

Thanks for the help. appreciate it.

---

<div class="post-metadata">

**Author:** ![hanshinlee77](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hanshinlee77/32/32867_2.png) [@hanshinlee77](https://discourse.julialang.org/u/hanshinlee77)\
**Post date:** [February 11, 2022, 9:55pm UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/4 "2022-02-11T21:55:02Z")

</div>

**Update**  
I think I made it work.

I wasn’t paying attention at all to the asynchronous nature of Sockets.jl which appears based on libuv package.

The revised code is now,

```julia
using Sockets
using Observables

# Function to read from the server asynchronously and update Observable 'reply' when there is a response from the server
function readTCS(tcs::TCPSocket,reply)
    task = @async try
        while isopen(tcs)
            In = String(readavailable(tcs))
            if !isempty(In)
                println("Read from TCS, check reply.")
                reply[] = In
            end
        end
        println("readTCS task finished normally.")
    catch e
        println("readTCS task finished with $e.")
    end
    return task
end

# Connect to the server and display socket and peer details
inet_addr = Sockets.InetAddr(IPv4("198.214.229.46"),22401)
tcs = Sockets.connect(inet_addr)
sockname = getsockname(tcs)
peername = getpeername(tcs)
println("getsockname(tcs) returns : ip $(sockname[1]) port $(sockname[2]) : host")
println("getpeername(tcs) returns : ip $(peername[1]) port $(peername[2]) : remote")

# Set up an observable to monitor changes in the response from the server
reply = Observable("")
reply_change = observe_changes(reply)

# Run readTCS() task
readTask = readTCS(tcs,reply)

# Set up even handler when Observable reply changes and print out the changed value (String)
replyObs = on(reply_change) do drep
        println("reply[] ==> $drep")
end

# Set up an example command to the server
N = 100
cmd = "iraf"
ncmd = length(cmd)
buf = zeros(UInt8,N)
buf[1:ncmd] .= codeunit(cmd)

```

After running this portion of the script, buf can be written to tcs and the corresponding message (String) from the server is stored to reply and printed out as,

```julia
julia> write(tcs,buf);

julia> Read from TCS, check reply.
reply[] ==> 2 6 Fri Feb 11 2022( 42) 21:48:51.6 0 0 0
 LST/HA + 0:20:30.49 + 0: 0: 0.04 180.0 50.8 1.5792
 MEAN + 0:19:25.86 -20:13:46.6 2000.0 0.000 0.00
 APP + 0:20:31.28 -20: 6:40.7 2022.1
 REFRA + 0:20:30.45 -20: 0: 0.0 2022.1
 RAW + 0:20:30.45 -20: 0: 0.0 2022.1
 107 F 36616

julia> split(reply_change[],'\n')
8-element Vector{SubString{String}}:
 " 2 6 Fri Feb 11 2022( 42) 21:48:51.6 0 0 0"
 " LST/HA + 0:20:30.49 + 0: 0: 0.04 180.0 50.8 1.5792"
 " MEAN + 0:19:25.86 -20:13:46.6 2000.0 0.000 0.00"
 " APP + 0:20:31.28 -20: 6:40.7 2022.1"
 " REFRA + 0:20:30.45 -20: 0: 0.0 2022.1"
 " RAW + 0:20:30.45 -20: 0: 0.0 2022.1"
 " 107 F 36616"
 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ⋯ 33 bytes ⋯ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"

```

I suppose the reason that read() hanged in my first post was due to read() was blocking everything whereas in readTCS() above it is running asynchronously and hence non blocking.

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [February 12, 2022, 11:30am UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/5 "2022-02-12T11:30:24Z")

</div>

I don’t think you need the task-handling for the simple `read()` you’re doing. With a few lines of Python to mimic the _server_ you’re using your original Julia code seems to work fine:

```julia
melis@juggle 12:25:~$ cat s.py 
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 22401))
s.listen(1)
t,a = s.accept()
r = t.recv(100)
print('got %d bytes: %s' % (len(r), r))
t.sendall('hello!'.encode('utf8'))

melis@juggle 12:25:~$ cat s.jl
# Import Sockets module
using Sockets

# Establish socket connection to the TCP server
tcs = connect(TCPSocket(;delay=false), IPv4("127.0.0.1"), 22401)

# Create 100 byte Char array with command "iraf"
a = Array{Char,1}(undef,100)
a[1:4] = collect("iraf")

# Write the message to the socket
write(tcs,String(a))

# Read message back from the server
r = read(tcs)
println("read '$(r)'")

close(tcs)

# terminal 1 
melis@juggle 12:27:~$ python s.py 
got 100 bytes: b'iraf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

# terminal 2
melis@juggle 12:27:~$ j s.jl 
read 'UInt8[0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x21]'

```

After all, your Python of the _client_ also used a blocking call to `sock.recv(1024)` and it worked, so I don’t see why the Julia equivalent would not work similarly.

Edit: one thing that is different in the Julia code is that the `read()` call doesn’t specify the amount of bytes to read. That might cause a longer wait before it returns. E.g. you can try `read(tcs, 40)` to read at most 40 bytes.

---

<div class="post-metadata">

**Author:** ![hanshinlee77](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hanshinlee77/32/32867_2.png) [@hanshinlee77](https://discourse.julialang.org/u/hanshinlee77)\
**Post date:** [February 12, 2022, 6:45pm UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/6 "2022-02-12T18:45:36Z")

</div>

That is exactly what I thought Sockets.jl should be able to do. Thanks for doing a quick test with the python server and julia client. This is a great pointer for me.

I tried this on this server without the task handler, but with readavailable() method rather than read().  
And it worked. In this case, I commented out the task handler readTCS() and the observable event handler.

read(tcs) still hangs, but as you said I tried it with the number of bytes specified (400 in this case) and voila! it worked.

```julia
julia> writeTCS(tcs,"iraf"); a = split(String(read(tcs,400)),'\n')
Request sent to tcs normally.
8-element Vector{SubString{String}}:
 " 2 6 Sat Feb 12 2022( 43) 18:25: 0.2 0 0 0"
 " LST/HA +21: 0: 2.14 - 0: 0: 0.69 180.0 50.8 1.5791"
 " MEAN +20:58:50.30 -20:11:37.7 2000.0 0.000 0.00"
 " APP +21: 0: 3.82 -20: 6:37.8 2022.1"
 " REFRA +21: 0: 2.83 -19:59:59.1 2022.1"
 " RAW +21: 0: 2.83 -19:59:59.1 2022.1"
 " 107 F 37306"
 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ⋯ 33 bytes ⋯ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"

```

Note that writeTCS() is a method I added to make it easy for me to parse a string command into 100-byte long message to the server as,

```julia
function writeTCS(tcs::TCPSocket,request::String)
   Lcmd = length(request)
   Lmax = 100
   try
        @assert 0 < Lcmd <= Lmax
        buf = zeros(UInt8,Lmax)
        buf[1:Lcmd] .= codeunits(request)
        @assert write(tcs,buf) == Lmax
        println("Request sent to tcs normally.")
   catch e
        println("Failed to send request: $e.")
   end
end

```

But when I tried to read more than 400 bytes after writeTCS(), read(tcs,N) where N \> 400 hangs. So, it looks like the server response is 400-byte long for this particular request (a piece of new information about this server). I think this should do the job for me, but readavailable(tcs) seems working as well, in which case I don’t think I have to know the exact number of bytes of the server response. The size of server responses for other requests may be different (nothing is said about it in its manual). So, readavailable() would work safe for the time being.

I think my problem has been solved and I learned a lot from it. Thanks very much for all great suggestions!

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 12, 2022, 8:42pm UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/7 "2022-02-12T20:42:50Z")

</div>

> [@paulmelis](#):
>
> one thing that is different in the Julia code is that the `read()` call doesn’t specify the amount of bytes to read. That might cause a longer wait before it returns.

Ah of course, this will certainly be the problem: `read()` will read bytes from the socket until it’s closed. Which will always block forever unless the remote side closes the connection.

> [@hanshinlee77](#):
>
> readavailable(tcs) seems working as well, in which case I don’t think I have to know the exact number of bytes of the server response

`readavailable()` might work for you, but it’s not very reliable in general — it’ll only read “some” bytes which might be less than the number of bytes sent by the remote side. And if you call it when no data is available it can block until one byte is available.

Ideally it’s better to use `read()` with the exact message size so you know you got the whole packet. Well-designed protocols generally have some framing with a fixed size header containing the total size of the next message packet for this purpose. It sounds like this is all implicit for the black box you’re trying to talk to. My suggestion would be to figure out the response size for each different request type (hopefully it never varies!?) then hardcode that somewhere.

(For this awkward situation it would be best if Julia had an easy way to “read everything until a timeout”, but that’s not builtin. You can simulate it with a `readavailable` loop in a separate task and some `Channel` plumbing, etc, but it really should be easier.)

---

<div class="post-metadata">

**Author:** ![hanshinlee77](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hanshinlee77/32/32867_2.png) [@hanshinlee77](https://discourse.julialang.org/u/hanshinlee77)\
**Post date:** [February 12, 2022, 8:46pm UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/8 "2022-02-12T20:46:42Z")

</div>

That is a great point Chris. And I now understand why read hangs in this case. I am going to follow your suggestion to find out the response sizes and hard code them in my client script. Thanks!

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 12, 2022, 10:38pm UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/9 "2022-02-12T22:38:04Z")

</div>

Sure, no problem, I hope the response size from the server is fixed!

(It would be _possible_ for the server to be particularly badly behaved and give a variable response size with no message framing. If this was the case you’d be forced into heuristics with timeouts and message parsing. I don’t think I’ve seen a case of this in practice before, however.)

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [February 13, 2022, 12:54am UTC](https://discourse.julialang.org/t/using-julia-sockets-to-send-message-to-an-existing-tcp-socket/76191/10 "2022-02-13T00:54:14Z")

</div>

It has to signal that the message is done somehow. The options are basically:

1. Close the connection.
2. Convey the length in advance.
3. Send an end of message marker inline.
