7

I'm trying to code a small web server in python to catch an HTTP post. But I'm having an issue with the socket.gethostname part of it

here is my sample code

import socket

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket.bind((socket.gethostname(), 8089))
serversocket.listen(1)


while True:
    connection, address = serversocket.accept()
    buf = connection.recv(164)
    print buf

If i change

serversocket.bind((socket.gethostname(), 8089))

to

serversocket.bind(("localhost", 8089))

Everything is fine I can telnet into it, but I need to be able to connect from another web server on the internet so I need to use socket.gethostname but this block my telnet.

Arriflex
  • 145
  • 1
  • 2
  • 7
  • "another web server on the internet" or just your LAN? – OneCricketeer Mar 21 '16 at 17:52
  • Also "I'm trying to code a small web server in python" - Have you tried using [Flask](http://flask.pocoo.org/docs/0.10/quickstart/)? – OneCricketeer Mar 21 '16 at 17:53
  • On the internet !? i will look into Flask right now – Arriflex Mar 21 '16 at 17:55
  • Well, your router will need to forward a port to your server, which is why I asked. Otherwise your firewall will block it. – OneCricketeer Mar 21 '16 at 18:03
  • 3
    Try `serversocket.bind(("0.0.0.0", 8089))` that should bind to all of your external addresses. – tdelaney Mar 21 '16 at 18:19
  • But as others have mentioned, your local server can't receive incoming connections from the internet if a network firewall or NAT is in the way. You will need to configure your firewall/NAT or if you control the protocol between the web server and this server... have this server make the connection instead of the other way around. – tdelaney Mar 21 '16 at 18:26
  • Thanks @tdelaney it worked using serversocket.bind(("0.0.0.0", 8089)) – Arriflex Mar 22 '16 at 13:43
  • 1
    I was configuring Raspberry Pi as server, and there `socket.gethostname()` simply returns `raspberrypi`, haha. So, be careful, guys :) – San Askaruly Oct 21 '20 at 12:08

1 Answers1

17

You are using a clever trick to get your servers "real" address when potentially several network interfaces are open. serversocket.bind((socket.gethostname(), 8089)) can be broken down to

hostname = socket.gethostname()
dns_resolved_addr = socket.gethostbyname(hostname)
serversocket.bind((dns_resolved_addr, 8089))

You get your local hostname and then ask DNS what it thinks your IP address is, and bind to that. That's the IP address external connections will use so you should use it too.

But it doesn't always work. DNS may not know what your server name is or your server may have a different name in DNS. One example is my home network where I don't have a DNS server and the DHCP addresses handed out by my modem don't appear in a name server anywhere. A similar problem exists if your corporate DHCP doesn't register your hostname with its local DNS.

On my machine, when I go through the steps I get

>>> socket.gethostbyname(socket.gethostname())
'127.0.1.1'

Notice it was 127.0.1.1 ... I think that's some weird Ubuntu thing to keep its routing tables from getting confused. Anyway, one solution is to try to resolve the address and if you don't like it, fall back to a default.

>>> my_ip = socket.gethostbyname(socket.gethostname())
>>> if my_ip.startswith('127.0.'):
...     my_ip = '0.0.0.0'
... 
>>> my_ip
'0.0.0.0'
tdelaney
  • 73,364
  • 6
  • 83
  • 116