pythonerlangpython-3.7erlang-otperlang-ports

Erlang echo server with python client is not echoing, python client not receiving response correctly


So I'm trying to get an erlang server started, which will echo back from my python client. I can see the connection is made, however the echo doesn't actually happen. Can anybody point me to the right solution?

I'm using python3 as my client driver.

Here is my erlang server: I start it with echo:accept(6000).

-module(echo).
-export([accept/1]).

%% Starts an echo server listening for incoming connections on
%% the given Port.
accept(Port) ->
    {ok, Socket} = gen_tcp:listen(Port, [binary, {active, true}, {packet, line}, {reuseaddr, true}]),
    io:format("Echo server listening on port ~p~n", [Port]),
    server_loop(Socket).

%% Accepts incoming socket connections and passes then off to a separate Handler process
server_loop(Socket) ->
    {ok, Connection} = gen_tcp:accept(Socket),
    Handler = spawn(fun () -> echo_loop(Connection) end),
    gen_tcp:controlling_process(Connection, Handler),
    io:format("New connection ~p~n", [Connection]),
    server_loop(Socket).

%% Echoes the incoming lines from the given connected client socket
echo_loop(Connection) ->
    receive
        {tcp, Connection, Data} ->
        gen_tcp:send(Connection, Data),
        echo_loop(Connection);
    {tcp_closed, Connection} ->
        io:format("Connection closed ~p~n", [Connection])
    end.

here is my python client:

import socket
import sys

# 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 = ('localhost', 6000)
print(sys.stderr, 'connecting to %s port %s' % server_address)
sock.connect(server_address)
try:
    
    # Send data
    message = 'This is the message.  It will be repeated.'
    convertedString = message.encode('utf-8')
    print(sys.stderr, 'sending "%s"' % message)
    sock.sendall(convertedString)

    # Look for the response
    amount_received = 0
    amount_expected = len(message)
    
    while amount_received < amount_expected:
        data = sock.recv(16).decode('utf-8')
        amount_received += len(data)
        print(sys.stderr, 'received "%s"' % data)

finally:
    print(sys.stderr, 'closing socket')
    sock.close()

I think the problem is it just hangs after sending, and now it's waiting for a response, I think I might not be receiving the string in the right way.


Solution

  • One issue is that you have {packet, line} and the message does not include a new line, so the echo server keeps waiting for the message to be completed before sending it to the handler.

    Also, you should be careful with the active option, as any data that is received during the controlling_process/2 call will remain in the previous handler. You should start the accepted socket with {active, false} and then set it to true | pos_integer() when the socket is managed by the handler.