I'm having a little trouble with sockets in Python. Whenever someone connects it works fine but if they disconnect the server program closes. I want the server program to remain open after the client closes. I'm using a while True loop to keep the connection alive but once the client closes the connection the server closes it's connection.
Here is the client:
import socket, sys
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = sys.argv[1]
port = int(sys.argv[2])
conn.connect((host, port))
print("Connected to host " + sys.argv[1])
td = 1
while td == 1:
msg = raw_input('MSG: ')
Here is the server:
import socket, sys
socket.setdefaulttimeout(150)
host = ''
port = 50005
socksize = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("Server started on port: %s" % port)
s.listen(1)
print("Now listening...\n")
conn, addr = s.accept()
while True:
print 'New connection from %s:%d' % (addr[0], addr[1])
data = conn.recv(socksize)
if not data:
break
elif data == 'killsrv':
conn.close()
sys.exit()
else:
print(data)
Keep a single server socket outside of the loop -- the loop needs to start before accept(). Just put the ServerSocket creation into a separate try/catch block. Otherwise, you'll open a new socket that will try to listen on the same port, but only a single connection has been closed, not the serverSocket.
Strictly speaking, you're supposed to use shutdown on a socket before you close it. The shutdown is an advisory to the socket at the other end. Depending on the argument you pass it, it can mean “I'm not going to send anymore, but I'll still listen”, or “I'm not listening, good riddance!”.
Python provides two levels of access to network services. At a low level, you can access the basic socket support in the underlying operating system, which allows you to implement clients and servers for both connection-oriented and connectionless protocols.
A new Python socket by default doesn't have a timeout. Its timeout defaults to None. Not setting the connection timeout parameter can result in blocking socket mode. In blocking mode, operations block until complete or the system returns an error.
If a client closes a connection, you want it to close the socket.
It seems like there's a bit of a disconnect here that I'll try to elaborate on. When you create a socket, bind, and listen, you've established an open door for others to come and make connections to you.
Once a client connects to you, and you use the accept()
call to accept the connection and get a new socket (conn
), which is returned for you to interact with the client. Your original listening socket is still there and active, and you can still use it to accept more new connections.
Looking at your code, you probably want to do something like this:
while True:
print("Now listening...\n")
conn, addr = s.accept()
print 'New connection from %s:%d' % (addr[0], addr[1])
data = conn.recv(socksize)
if not data:
break
elif data == 'killsrv':
conn.close()
sys.exit()
else:
print(data)
Please note that this is just a starting point, and as others have suggested you probably want to use select()
along with forking off processes or spawning threads to service each client.
Your code is only accepting a single connection - the loop only deals with the first accepted connection and terminates as soon as it lost. This is way your server exists:
data = conn.recv(socksize)
if not data:
break
What you will need to do is to accept several connections, while handling each of those in it's own loop. Note that it does not have to be a real loop for each socket, you can use a select
-based approach to query which of the sockets has an event associated with it (data available, connection lost etc.) and then process only those sockets, all in the same loop.
You can also use a multi threaded / multi process approach, dealing with each client in it's own thread or process - I guess you won't run into scaling issues when playing around.
See:
http://docs.python.org/library/select.html
http://docs.python.org/library/multiprocessing.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With