I am following this example,
#!/usr/bin/python # This is server.py file
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
c.send('Thank you for connecting')
c.close() # Close the connection
and I am getting this error despite good network:
>>> s.bind((host, port))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Applications/anaconda/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.gaierror: [Errno 8] nodename nor servname provided, or not known
How can I fix this?
Let's take a look at the docs:
socket.gethostname()
Return a string containing the hostname of the
machine where the Python interpreter is currently executing.
If you want to know the current machine’s IP address, you may want to
use gethostbyname(gethostname()). This operation assumes that there is
a valid address-to-host mapping for the host, and the assumption does
not always hold.
Note: gethostname() doesn’t always return the fully qualified domain
name; use getfqdn() (see above).
I guess this is what's happening: bind is trying to establish IP address for the host, but it fails. Run host = socket.gethostbyname(socket.gethostname()) and instead of a valid IP address you'll most probably see the same error as when calling bind.
You say the returned hostname is valid, but you have to make sure it's recognised by the DNS responder. Does the resolution work when doing, for example, ping {hostname} from the command line?
Possible solutions would be:
Fix your local DNS resolution.
Use host = socket.getfqdn() (in case you were not getting the fully qualified name which then couldn't be resolved properly). Even if it works I think you should try and fix the local resolution.
Use empty host (host = ''), which on bind would mean "listen on all available interfaces". (This is the first example in the docs.)
Related
I am trying to set up a UDP unicast between two linux-machines on my local network, using the python sockets library. I manage to send and receive the package using the following code:
Send
import socket
HOST = '192.168.1.194' # IP of remote machine
PORT = 47808
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto('Hello UDP', (HOST, PORT))
s.close()
Receive
import socket
HOST = ''
PORT = 47808
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((HOST, PORT))
while True:
try:
data, addr = s.recvfrom(1024)
print 'Received: {0} # {1}'.format(data, addr)
except KeyboardInterrupt:
break
s.close()
However, binding to '' makes the receiving code accept packets from any local interface. If I try to bind to the IP address of the sending machine specifically (changing HOST = ''to HOST = '192.168.1.130' in the receiving code), I get a socket.error: [Errno 99] Cannot assign requested address. No other services are using the port, and I have tried different ports with no change in behaviour. How can I configure my socket to only receive packets from a specific address?
First, let's deal with the error you are seeing. .bind() names the local end of the socket, not the remote. So the host part must refer to the local machine (e.g., 'localhost', '127.0.0.1, '192.168.1.194', or '' (wildcard for all local interfaces).) So, when you specify an address that isn't local to the machine running .bind(), you get an error.
Second, there is no way to "configure my socket to only receive packets from a specific address." As an alternative, you can use the returned address from .recvfrom() to ignore data you don't care about.
data, addr = s.recvfrom(1024)
if addr != '192.168.1.130':
continue
I am attempting to write a very simple server in python.
import socket
import sys
# Create a TCP/IP socket to listen on
server = socket.socket(socket.SOL_SOCKET, socket.SOCK_STREAM)
# Prevent from 'address already in use' upon server restart
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Bind the socket to port 8081 on all interfaces
server_address = ('localhost', 8081)
print 'starting up on %s port %s' % server_address
server.bind(server_address)
I have read what I think to be correct documentation for the socket library, and it suggests that the server.bind() takes an argument of a tuple. However, I get this error:
starting up on localhost port 8081
Traceback (most recent call last):
File "pyserver.py", line 14, in <module>
server.bind(server_address)
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
TypeError: argument must be string or read-only character buffer, not tuple
I have changed the argument to only a string, as the error warning suggests, and I get a
[Errno 98] Address already in use
error. I thought that the 8th line was in place to prevent that. What is going on?
The first argument to the socket.socket should be address family:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
^^^^^^^^^^^^^^
Except that, your code should work.
Reason of the error message: argument must be string ...
In Linux, the value of the socket.SOL_SOCKET is 1 which is equal to the value of socket.AF_UNIX. Unix domain socket (AF_UNIX) use path (string) as a address
>>> import socket
>>> socket.AF_UNIX
1
>>> socket.SOL_SOCKET
1
UPDATE
Regarding Already already in use error, see SO_REUSEADDR and AF_UNIX.
I use a port in my python program and close it,now I want to use it again.Just that port not another port.
Is there any way to force OS to free port with python?
#!/usr/bin/python # This is server.py file
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12349
portt = 12341 # Reserve a port for your service.
s.bind((host, portt)) # Bind to the port
s.connect((host, port))
s.close
ss = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
ss.bind((host, portt))
s.close
but the output is:
Traceback (most recent call last):
File "client.py", line 17, in <module>
ss.bind((host, portt))
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 98] Address already in use
You'll never be able to force the OS (with any sort of reasonable effort) to release a socket.
Instead you just want to say you don't care with setsockopt
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
This means that the option takes place at the Socket Object Level SOCKET (as opposed to the TCP or something else) and you're setting the Socket Option REUSEADDR (you're telling the OS that it's OK, you really do want to listen here). And finally, you're turning the option on with 1, rather than off (with 0).
I have copied simple server/client python programs to test some socket communications.
If host is defined as 'localhost' or '', they work.
If I substitute the actual hostname in /etc/hosts, they fail with the socket.gaierror 2.
socket.gethostname() returns the correct value
as does 'hostname' on the command line.
Here is the server code that fails
#!/usr/bin/env python
"""
A simple echo server
"""
import socket
import sys
host = ''
port = 50000
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
print( " using host [%s] " % (host) )
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
data = client.recv(size)
print( data )
if data:
client.send(data)
client.close()
and here is the client program
#!/usr/bin/env python
"""
A simple echo client
"""
import socket
host = 'localhost'
port = 50000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
s.connect((host,port))
s.send('Hello, world')
data = s.recv(size)
s.close()
print( 'Received:', data )
This is the actual output from the server.py while using the gethostname() call.
using host [HP-linux]
Traceback (most recent call last):
File "server.py", line 18, in <module>
s.bind((host,port))
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.gaierror: [Errno -2] Name or service not known
Like I said, if I comment out the 'gethostname() calls, they work.
I have not been able to find any posts about gaierrors that have answers that work to solve this issue.
This running on SuSE Linux 13.1, and python2.7.
Thanks
This issue was resolved by adding an alias to the /etc/hosts file.
No rational answer as to why this would work.
Binding the server on hostname you're actualy binding it on local address, this is because normally there's a line in /etc/hosts like this 127.0.1.1 somehostname, this is to use lo iface instead of eth on the same machine for optimization reasons. If you want to accept connections from all interfaces use '0.0.0.0' instead.
I simply did these steps.
Ran command:
hostname
Say it returned me a value 'yourHostName'
Make an entry in your /etc/hosts file as follows.
127.0.0.1 yourHostName localhost
Reference for this information is : format of /etc/hosts file. Which you can see here.
I am currently attempting to create a basic LAN socket server, which works correctly when I use both the client and the server on the same computer. When I attempt to use the client and server on two computers (mac and windows) the connection is consistently refused on the client side. Here is the error that I got on my mac:
Traceback (most recent call last):
File "/Users/*****/Desktop/Client V2.py", line 31, in <module>
s.connect((host, port))
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py",
line 224, in meth
return getattr(self._sock,name)(*args)
error: [Errno 61] Connection refused
On my windows I had the same error, only the number was different. I have turned off windows firewall for both incoming and outgoing connections, and I am confused as to what the actual issue is. Here is the code that I had for my ports:
Client
#Get host and port info to connect
host = 'localhost'
port = input ("What is the PORT number?")
I am not sure if these lines are necessary, perhaps they are the root cause of the problem:
try:
remote_ip = socket.gethostbyname(host)
except socket.gaierror:
#could not resolve
print "Hostname could not be resolved. Exiting"
sys.exit()
And finally, the actual code that connects. (I called the socket s)
s.connect((host, port))
Server
HOST = 'localhost' #Symbolic name meaning all available interfaces
PORT = input ("Enter the PORT number (1 - 10,000)")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket Created"
try:
s.bind((HOST, PORT))
except socket.error, msg:
print "Bind failed. Error Code : " + str(msg[0]) + " Message " + str(msg[1])
sys.exit()
print "Socket Bind Complete"
s.listen(10)
print "Socket now listening"
I am certain that I have done something really silly, but can someone please tell me what my mistake is (or if this is even possible cross-os). I already posted here, but no one responded. I have several other questions there, and it would be great if someone could attempt to answer them.
HOST = 'localhost' #Symbolic name meaning all available interfaces
doesn't mean "all available interfaces" but only the local machine via a special interface only visible to programs running on the same computer.
HOST = '0.0.0.0' #Symbolic name meaning all available interfaces
does mean all available network interfaces. Of course you can also bind to a specific network interface, in that case you just enter its ip address in the field.