Socket Server
Server Types
- BaseServer, defines APIs
- handle_request(), handle request once
- serve_forever(), calls handle_request() in an infinite loop
- TCPServer, use TCP/IP socket to communicate
- UDPServer, use UDP socket to communicate
- UnixStreamServer and UnixDatagramServer, use UDS to communicate
Handlers
- BaseRequestHandler
- setup(), called before the handle() method to perform any initialization actions required
- handle(), define what to do
- finish(), called after the handle() method to perform any clean-up actions required
#server.py
#!/usr/bin/python
import SocketServer
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print type(self.request), type(self.client_address), type(self.server)
print 'Client: ', self.client_address
print 'Server: ', self.server
print self.data
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
#client.py
#!/usr/bin/python
import socket
import sys
HOST, PORT = "localhost", 9999
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
data = raw_input("Eneter your message:\n");
sock.connect((HOST, PORT))
sock.sendall(data + "\n")
# Receive data from the server and shut down
received = sock.recv(1024)
finally:
sock.close()
print "Received: {}".format(received)
Flow Control
#server.py
#!/usr/bin/python
import SocketServer
import struct
class MyTCPHandler(SocketServer.BaseRequestHandler):
def __init__(self, request, client_address, server):
self.n = 0;
SocketServer.BaseRequestHandler.__init__(self, request, client_address, server)
def handle(self):
s = struct.Struct('f');
while True:
self.data = self.request.recv(s.size)
self.unpacked_data = s.unpack(self.data)
self.n += 1
print 'received: ', self.n, self.unpacked_data[0]
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
#client.py
#!/usr/bin/python
import random
import socket
import sys
import struct
HOST, PORT = "localhost", 9999
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s = struct.Struct('f');
num = 0;
sock.connect((HOST, PORT))
try:
while True:
n = random.random();
packed = s.pack(n);#pack data into a string
num += 1;
print 'Sent: ', num, n
sock.sendall(packed)
finally:
pass
#sock.close()
Threading and Forking
- Threads, use the ThreadingMixIn
- Processes, use the ForkingMixIn
#server.py
import threading
import SocketServer
import socket
class ThreadedEchoRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
# Echo the back to the client
data = self.request.recv(1024)
cur_thread = threading.currentThread()
response = '%s: %s' % (cur_thread.getName(), data)
print 'Received: ', response
class ThreadedEchoServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
if __name__ == '__main__':
address = ('localhost', 50007) # let the kernel give us a port
server = ThreadedEchoServer(address, ThreadedEchoRequestHandler)
ip, port = server.server_address # find out what port we were given
print ip, port
t = threading.Thread(target=server.serve_forever)
#t.setDaemon(True) # don't hang on exit
t.start()
print 'Server loop running in thread:', t.getName()
#server.socket.close()
import socket
import threading
address = ('localhost', 50007) # let the kernel give us a port
# Connect to the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(address)
# Send the data
message = 'Hello, world'
print 'Sending : "%s"' % message
len_sent = s.send(message)
# Clean up
s.close()