2

I want to use Unix sockets for 2 Python programs on the same system to talk to each other.

There are examples of binding to a socket file here: https://gist.github.com/jmhobbs/11276249

The often-used socketserver library also has a UnixStreamServer, and a UnixDatagramServer, which sounds like it deals with unix sockets as well, but there are no examples of either one, and as far as I can tell, it requires an IP and Port, rather than a file when initializing either a UnixStreamServer or UnixDatagramServer.

Are UnixDatagramServer and UnixStreamServer a different type of unix sockets that demonstrated here? Or am I just not seeing how to use them to connect to a socket file properly? Are there examples? Why would someone use UnixDatagramServer/UnixStreamServer over binding to a socket file directly, as in my link?

And when talking about IP sockets, the difference between TCP/UDP makes sense - one is reliable, while the other is not, without the overhead. In a world of sockets, where I assume there's no such thing as unreliable communication, why are there still 2 different types (Datagram vs Stream)?

3 Answers 3

7

As @GreenCloakGuy pointed out, you may want to use Pipes, but if you're set on using Unix sockets, here's a rough example of using StreamRequestHandler:

Server:

#!/usr/bin/env python3

from socketserver import UnixStreamServer, StreamRequestHandler, ThreadingMixIn
import os

os.unlink("/tmp/test")

class Handler(StreamRequestHandler):
    def handle(self):
        while True:
            msg = self.rfile.readline().strip()
            if msg:
                print("Data Recieved from client is: {}".format(msg))
            else:
                return

class ThreadedUnixStreamServer(ThreadingMixIn, UnixStreamServer):
    pass

with ThreadedUnixStreamServer('/tmp/test', Handler) as server:
    server.serve_forever()

Client:

#!/usr/bin/env python3

import socket
import sys 
import time

with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client:
    client.connect("/tmp/test")

    while True:
        client.send(b"Client 1: hi\n")
        time.sleep(1)

    client.close()

The ThreadingMixIn isn't necessary, but lets you run 2 clients, and receive messages from both of them at the same time. Copy the client code into "client1.py" and "client2.py", and change "Client 1" to "Client 2" in client2.py, running both, to see this in practice.

I'm no expert, but it sounds like while Pipes are more efficient, they have the disadvantage of having only one program linked to one other program. If you have multiple clients, and one server, Unix sockets, as demonstrated here, might be your best bet.

Sign up to request clarification or add additional context in comments.

3 Comments

How to change permission of the socket /tmp/test to ( 0o700)
with statement no need client.close() ?
@CSQGB the fact that you don't need to remember to close a resource is the primary reason to use a with statement, and that the with statement even exists, so no, you don't need to close if you're using with. It will close automatically when you exit the block
0
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#kate: syntax Python ;

# use them like so:

import          socket,               os , time
parent, child = socket.socketpair()

#child.close() # bad fdesc

pid           =                       os.fork()
if pid:
    #time.sleep(0.3)
    #child.close()
    print 'in   parent, sending    message'
    p =         parent.sendall('ping p')
    response1 = parent.recv(444)
    print      'response from child         :', response1
    p =         parent.close()

else:
    #time.sleep(0.7)
    #parent.close()

    print  'in child, waiting for message'
    message1 = child.recv(333)
    print  'message from parent         :', message1

    child.sendall('päng c')
    child.close()

#print "Ende" , pid
#print parent # , child
#print type(pid) , " -- " , type(child)

Comments

-1

for 2 Python programs on the same system to talk to each other

Don't use sockets. Use pipes.

A socket, in particular, is essentially a link between the Application layer and the Transfer layer, in networking. This is why you need so supply an IP and port number - those are the important addressing information for anyone looking at your computer externally. It's also why you have Datagram vs Stream - TCP and UDP are the two main transport layer protocols, and when building your link to the transport layer you need to specify which protocol you want to use. Sockets are meant for communication using the network - there are alternate, more efficient and easier, ways to communicate between two processes on the same system.

Pipes are more like file descriptors that are used specifically for inter-process communication. There are essentially two ways to use pipes - named pipes and anonymous pipes. If your "two python programs" are splitting off from one original program using something like multiprocessing, then anonymous pipes are what you might want to go with, and you can use os.pipe() to set that up. Otherwise, you'll need to figure out a consistent name and location for your pipe that both programs know, and initialize it on one end with os.mkfifo() then just open it like a regular file on the other end. This functionality seems to only be available on Unix, so if you're on Windows you might have to investigate other solutions.

9 Comments

I wonder if this will start a war. I suggested something similar when someone was using multiple IPv4 loopback addresses (127.0.0.0/8) for inter-process communication, and wanted the same thing for IPv6, which has only one loopback address (::1), but I was chastised that the network stack is much faster than other IPC methods. I'm not sure I believe that because it involves too many other processes, both on the way "out" and on the way "in."
@RonMaupin I guess you can use the loopback address (and listen on a particular port), but it very much seems like applying the wrong tool for the situation. I haven't done speed tests myself, but I doubt the loopback is overwhelmingly more efficient than the file protocol. Also seems like the kind of thing if you're worrying about it then you wouldn't be asking this question
"it very much seems like applying the wrong tool for the situation." I agree, but I was strongly told in no uncertain terms that I was wrong. It just seems so inefficient to assign individual loopback addresses to processes, then use the network stack for communication. The person asking the question would have had to re-architect the whole thing to make it work with IPv6, and he wasn't the one who got on me for suggesting that it was done incorrectly in the first place.
In the github gist link above, the example is clearly using a file, rather than an IP/PORT, and is using the socket module to set that up, implying a socket, and not a pipe, is in use. Your answer seems to suggest that sockets always use the network Transfer layer, which the example doesn't. Something doesn't sound right. Does the gist actually use pipes, rather than sockets (coming from an unfortunately-named module)? Why are there unix socket files if sockets always use the networking stack?
It's not that they actually use files, it's that you access them through file descriptors, which is not the same thing.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.