2

I have the situation where a service running in the background makes itself available for ASCII-based commands via a socket (SOCK_DGRAM) placed on the file system. I am able to successfully send commands to this interface but cannot receive any response generated by the background service.

As I understand it, the reason I am not receiving the service's response is because the underlying IPC is not technically between two processes, but is rather between to addresses. As such, it is necessary to bind my endpoint to a particular address location so the service knows were to send its response. However, the problem is that I do not want to pollute the directory space with too many additional socket files.

That is to say, I can make this work by simply doing something like:

struct sockaddr_un local;
int len;

s = socket(AF_UNIX, SOCK_DGRAM, 0);
local.sun_family = AF_UNIX;
strcpy(local.sun_path, "/path/to/some/dir/mySocketFile");
len = strlen(local.sun_path) + sizeof(local.sun_family);
bind(s, (struct sockaddr *)&local, len);
//Send commands to control interface of background service

And all is well, because by binding to mySocketFile the service has an address to which is will respond.

In short, is there a way to communicate to the service through its available socket interface and receive the response without binding the local endpoint such that it creates another socket-type file on the file system? i.e. some kind of a nameless socket, of sorts?

Of course, if anyone spots any misconceptions or misunderstandings in my logic please point them out.

sherrellbc
  • 4,650
  • 9
  • 48
  • 77
  • 2
    does this help? http://stackoverflow.com/questions/3324619/unix-domain-socket-using-datagram-communication-between-one-server-process-and – Dinesh Jul 24 '15 at 19:32
  • @Dinesh, Yep, the top answer at that link expresses basically what I thought was the cause with this. Essentially, the client *and* the server both require endpoints for proper communication - so each must have *bound* to a particular socket interface. I was asking this question to see if there was a possible method where the client does not generate this endpoint, but rather uses some kind of nameless socket that is not visibly created on the file system. – sherrellbc Jul 24 '15 at 19:36

1 Answers1

6

If the client does not bind its socket to an filesystem address, it still has a notional address assigned by the system (which may exist in the filesystem in /tmp somewhere, or may not exist in the filesystem at all, depends on the OS). The server can get this address by using the recvfrom(2) call to receive the incoming packets from clients -- this call takes additional sockaddr * and socklen_t * arguments that it fills in with the client socket address. You then use sendto(2) to send the reply back to the client.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • I thought this would be the case, but perhaps I am misusing the socket utilities. I am able to successfully send commands to the service, but by `recvfrom` blocks infinitely and never returns. I am certain the forward communicate is reaching the service because I command to shutdown behaves as expected. – sherrellbc Jul 24 '15 at 19:39
  • 1
    Is this implicit address created with a call to `sendto` or `connect`? – sherrellbc Jul 24 '15 at 19:40
  • If the `recvfrom` is blocking, then you're obviously not getting the commands in the server, because it is the `recvfrom` that gets to commands. If the service is getting the commands some other way then you're not using recvfrom. – Chris Dodd Jul 24 '15 at 19:40
  • I am not controlling the server listening for commands. What I mean was I am able to `sendto` my commands to the server (shutdown, for example), and the server's response is as expected (i.e. a shutdown). However, the server should respond with a status to the command; it is this response that I do not receive at the client. The server is actually a background service that I am communicating with, not anything I built or maintain. – sherrellbc Jul 24 '15 at 19:42
  • If the server is not sending responses back to your client, there's no way to change that without modifying the server. It sounds like your server is set up to receive commands only. – Chris Dodd Jul 24 '15 at 20:09
  • I know it sends responses, I am just not getting them for some reason. When I first started working on this I was able to get it working, but refactored the code and must be neglecting a step. To clarify, I have `connect`ed to the server's socket made available on the file system. I then simply `send` to the server and then `recv` on the same socket. – sherrellbc Jul 24 '15 at 20:12
  • 1
    I realized what the problem was: the service does not have appropriate permissions to write to the address I provide it with for a response. If I explicitly specify where I want the socket file to be generated (i.e. with `bind`) then I can `chmod` and I am able to successfully receive the server's responses, but otherwise I cannot. As such, if I do not `bind` and allow the OS to create a temporary address then the permission issue is still a problem. Is there any way around this? – sherrellbc Jul 24 '15 at 20:34