views:

360

answers:

6

I have a python program with many threads. I was thinking of creating a socket, bind it to localhost, and have the threads read/write to this central location. However I do not want this socket open to the rest of the network, just connections from 127.0.0.1 should be accepted. How would I do this (in Python)? And is this a suitable design? Or is there something a little more elegant?

A: 

If you do sock.bind((port,'127.0.0.1')) it will only listen on localhost, and not on other interfaces, so that's all you need.

nos
+4  A: 

Given a socket created with socket.socket(), you can use bind() before listening:

socket.bind(('127.0.0.1', 80))

Using the address 127.0.0.1 indicates that the socket should bind to the local interface only.

Greg Hewgill
Doesn't this bind to `INADDR_ANY`?
D.Shawley
Not according to http://www.amk.ca/python/howto/sockets/ although the actual Python documentation states that `''` is equivalent to `INADDR_ANY`. I'll update my answer.
Greg Hewgill
It binds to INADDR_ANY if you tell it to (by specfying a host of ''). Specifying a host of '127.0.0.1' binds it to 127.0.0.1
nos
+3  A: 

http://www.amk.ca/python/howto/sockets/

Shows some socket example. This tidbit is interesting to you I think

we used socket.gethostname() so that the socket would be visible to the outside world. If we had used s.bind(('', 80)) or s.bind(('localhost', 80)) or s.bind(('127.0.0.1', 80)) we would still have a "server" socket, but one that was only visible within the same machine.

I guess there is your answer (see below for correction)

As to the validity of using this method for thread communications. I'm not sure how well this handles multiple threads and reading/writing

EDIT

There seems to be a python recipe linked below that does some inter-thread communication

http://code.activestate.com/recipes/491281/

Have fun!

EDIT

The article is incorrect and as pointed out "s.bind(('', 80)) will bind to INADDR_ANY"

petantik
That article is incorrect. s.bind(('', 80)) will bind to INADDR_ANY.
JimB
Thanks for that I'll edit to reflect
petantik
A: 

You might want to use the queue module from the standard library instead. It's designed specifically to facilitate communication between threads. A quote from the docs:

The Queue module implements multi-producer, multi-consumer queues. It is especially useful in threaded programming when information must be exchanged safely between multiple threads. The Queue class in this module implements all the required locking semantics. It depends on the availability of thread support in Python; see the threading module.

Michał Marczyk
+2  A: 

If you are running on a UNIX-based system, you might want to consider using UNIX Domain Sockets instead of Internet sockets. I think something like the following should work:

>>> # in one window/shell
>>> import socket
>>> sd = socket.socket(socket.AF_UNIX)
>>> sd.bind('/path/to/my/socket')
>>> sd.listen(5)
>>> (client,addr) = sd.accept()
>>> client.recv(1024)
'hello'
>>>

>>> # in a different shell
>>> import socket
>>> sd = socket.socket(socket.AF_UNIX)
>>> sd.connect('/path/to/my/socket')
>>> sd.send('hello')
D.Shawley
Using a TCP/IP socket on the loopback device has the advantage (or disadvantage, if you will) that it could be accessed via a SSH tunnel for example.
Joachim Sauer
A UNIX Domain Socket offers the same functionality since it is bound to the file system. I tend towards them because they are not as resource heavy as an IP socket.
D.Shawley
A: 

notionOn TCP/IP networks 127.0.0.0/8 is a non-routeable network, so you should not be able to send an IP datagram destined to 127.0.0.1 across a routed infrastructure. The router will just discard the datagram. However, it is possible to construct and send datagrams with a destination address of 127.0.0.1, so a host on the same network (IP sense of network) as your host could possibly get the datagram to your host's TCP/IP stack. This is where your local firewal comes into play. Your local (host) firewall should have a rule that discards IP datagrams destined for 127.0.0.0/8 coming into any interface other than lo0 (or the equivalent loopback interface). If your host either 1) has such firewall rules in place or 2) exists on its own network (or shared with only completely trusted hosts) and behind a well configured router, you can safely just bind to 127.0.0.1 and be fairly certain any datagrams you receive on the socket came from the local machine. The prior answers address how to open and bind to 127.0.0.1.

Dom Brezinski