msantos / procket

Erlang interface to low level socket operations
http://blog.listincomprehension.com/search/label/procket
BSD 3-Clause "New" or "Revised" License
283 stars 80 forks source link

Problem with unix domain sockets #11

Closed PatrickCosmo closed 11 years ago

PatrickCosmo commented 11 years ago

I'm using procket to communicate with a server using unix domain sockets. I can connect to the service and write data to the socket, but the data is never sent until I close the socket.

If I'm only sending a one-way message to the service, this works beautifully.

But if I need to get a response from the service, I can't make it happen: the data never sends until I close the socket, and once the socket is closed of course I cannot get a reply.

Here is my code, simplified:

initSocket(SocketFile) -> Len = byte_size(SocketFile), UnixDomainSocket = <<( procket:sockaddr_common(?PF_LOCAL, Len))/binary, SocketFile/binary, 0:((procket:unix_path_max()-Len)*8)

, UnixDomainSocket.

sendData(SocketFile, Data) -> {ok, Socket} = procket:socket(?PF_LOCAL, ?SOCK_STREAM, 0), UnixSocket = initSocket(SocketFile), Result = procket:connect(Socket, UnixSocket), case Result of ok -> WriteResult = procket:write(Socket, Data),

at the above point, no data is sent, and it won't be sent until I call

procket:close(Socket).

calling procket:read(Socket, DataSize) does nothing of course, I never get a response from the service bc it hasn't received my request.

Any ideas?

msantos commented 11 years ago

On Thu, Sep 05, 2013 at 11:14:07AM -0700, PatrickCosmo wrote:

I'm using procket to communicate with a server using unix domain sockets. I can connect to the service and write data to the socket, but the data is never sent until I close the socket.

If I'm only sending a one-way message to the service, this works beautifully.

But if I need to get a response from the service, I can't make it happen: the data never sends until I close the socket, and once the socket is closed of course I cannot get a reply.

Here is my code, simplified:

initSocket(SocketFile) -> Len = byte_size(SocketFile), UnixDomainSocket = <<( procket:sockaddr_common(?PF_LOCAL, Len))/binary, SocketFile/binary, 0:((procket:unix_path_max()-Len)*8)

, UnixDomainSocket.

sendData(SocketFile, Data) -> {ok, Socket} = procket:socket(?PF_LOCAL, ?SOCK_STREAM, 0), UnixSocket = initSocket(SocketFile), Result = procket:connect(Socket, UnixSocket), case Result of ok -> WriteResult = procket:write(Socket, Data),

at the above point, no data is sent, and it won't be sent until I call

procket:close(Socket).

calling procket:read(Socket, DataSize) does nothing of course, I never get a response from the service bc it hasn't received my request.

Any ideas?

It looks as if you've done everything right from the client side but it's hard to say without knowing more about the server.

This might happen if the server is waiting for the client to send a complete message. For example, the message format prefaces the packet with a length and the server is blocking in read(), waiting for N bytes. Or the server is waiting for some bytes to indicate an end of message. When the client calls close(), the server's read() returns and the server continues processing the data.

You can check by strace'ing the server process. If it is reading the data you are sending from the client, then it's possible the client is sending a packet that is malformed in some way.

PatrickCosmo commented 11 years ago

Thanks Michael, I have a simple test service written in nodejs that does nothing but listen for data, and print what it receives out to the console, and echoes back "Hi". I have "clients" of this service I've written in Java, NodeJS and C++. All of them work fine. It's just the erlang client that doesn't work, the data never gets sent until I close the socket. I can send you the nodejs service if you like. I'm pretty sure the problem is not with the service. If it is, I'm at a loss to understand why my other 3 clients work fine, and the service itself is only a few lines of code. I'm out of ideas really. Patrick

Date: Thu, 5 Sep 2013 13:51:05 -0700 From: notifications@github.com To: procket@noreply.github.com CC: patrickcosmo@hotmail.com Subject: Re: [procket] Problem with unix domain sockets (#11)

On Thu, Sep 05, 2013 at 11:14:07AM -0700, PatrickCosmo wrote:

I'm using procket to communicate with a server using unix domain sockets. I can connect to the service and write data to the socket, but the data is never sent until I close the socket.

If I'm only sending a one-way message to the service, this works beautifully.

But if I need to get a response from the service, I can't make it happen: the data never sends until I close the socket, and once the socket is closed of course I cannot get a reply.

Here is my code, simplified:

initSocket(SocketFile) ->

    Len = byte_size(SocketFile),

    UnixDomainSocket = <<( procket:sockaddr_common(?PF_LOCAL, Len))/binary,

            SocketFile/binary,

            0:((procket:unix_path_max()-Len)*8)

            >>,

    UnixDomainSocket.

sendData(SocketFile, Data) ->

    {ok, Socket} = procket:socket(?PF_LOCAL, ?SOCK_STREAM, 0),

    UnixSocket = initSocket(SocketFile),

    Result = procket:connect(Socket, UnixSocket),

    case Result of

            ok ->

                    WriteResult = procket:write(Socket, Data),

at the above point, no data is sent, and it won't be sent until I call

procket:close(Socket).

calling procket:read(Socket, DataSize) does nothing of course, I never get a response from the service bc it hasn't received my request.

Any ideas?

It looks as if you've done everything right from the client side but it's

hard to say without knowing more about the server.

This might happen if the server is waiting for the client to send

a complete message. For example, the message format prefaces the

packet with a length and the server is blocking in read(), waiting for

N bytes. Or the server is waiting for some bytes to indicate an end of

message. When the client calls close(), the server's read() returns and

the server continues processing the data.

You can check by strace'ing the server process. If it is reading the

data you are sending from the client, then it's possible the client is

sending a packet that is malformed in some way.

— Reply to this email directly or view it on GitHub.

msantos commented 11 years ago

On Fri, Sep 06, 2013 at 06:29:52AM -0700, PatrickCosmo wrote:

Thanks Michael, I have a simple test service written in nodejs that does nothing but listen for data, and print what it receives out to the console, and echoes back "Hi". I have "clients" of this service I've written in Java, NodeJS and C++. All of them work fine. It's just the erlang client that doesn't work, the data never gets sent until I close the socket.

Definitely would not rule out a bug in procket.

Are the other clients sending a linefeed character or other EOL character?

I can send you the nodejs service if you like.

Sure, that would be great.

I'm pretty sure the problem is not with the service.

Doubt it is a problem with the service.

If it is, I'm at a loss to understand why my other 3 clients work fine, and the service itself is only a few lines of code. I'm out of ideas really.

One thing you can try: print out the data you're sending in hex in one of the working clients and in the Erlang client. Compare them byte for byte and make sure they are sending the same data.

PatrickCosmo commented 11 years ago

You're correct, adding an '\n' fixed it. Eesh. Sometimes the most obvious things ...

On 2013-09-06, at 11:06 AM, "Michael Santos" notifications@github.com wrote:

On Fri, Sep 06, 2013 at 06:29:52AM -0700, PatrickCosmo wrote:

Thanks Michael, I have a simple test service written in nodejs that does nothing but listen for data, and print what it receives out to the console, and echoes back "Hi". I have "clients" of this service I've written in Java, NodeJS and C++. All of them work fine. It's just the erlang client that doesn't work, the data never gets sent until I close the socket.

Definitely would not rule out a bug in procket.

Are the other clients sending a linefeed character or other EOL character?

I can send you the nodejs service if you like.

Sure, that would be great.

I'm pretty sure the problem is not with the service.

Doubt it is a problem with the service.

If it is, I'm at a loss to understand why my other 3 clients work fine, and the service itself is only a few lines of code. I'm out of ideas really.

One thing you can try: print out the data you're sending in hex in one of the working clients and in the Erlang client. Compare them byte for byte and make sure they are sending the same data. — Reply to this email directly or view it on GitHub.

msantos commented 11 years ago

On Fri, Sep 06, 2013 at 08:08:55AM -0700, PatrickCosmo wrote:

You're correct, adding an '\n' fixed it. Eesh. Sometimes the most obvious things ...

Don't know how many times I've forgotten the '\n'. Glad it works! Let me know if you have any more questions!