编写一个SocketServer需要实现以下步骤
- 编写一个handler类,继承BaseRequestHandler,重写handle()方法
- 针对是TCP还是UDP,生成一个server对象
- 调用server对象的handle_request或者serve_forever方法
服务器端:
#coding:utf-8 import SocketServer class MyTCPHandler(SocketServer.BaseRequestHandler): def handle(self): self.data = self.request.recv(1024).strip() #client_address为元组,(client_addr,client_port) print self.client_address print "{} wrote:".format(self.client_address[0]) print self.data self.request.sendall(self.data.upper()) if __name__ == "__main__": HOST,PORT = "localhost",9999 server = SocketServer.TCPServer((HOST,PORT),MyTCPHandler) server.serve_forever()
客户端:
#coding:utf-8 import socket import sys HOST,PORT = "localhost",9999 data = raw_input("please input your info:") print "data:",data sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) try: sock.connect((HOST,PORT)) sock.sendall(data + ' ') received = sock.recv(1024) print "received:",received finally: sock.close()
#format函数可以接受不限个参数,位置可以不按顺序,可以不用或者使用多次 print '{0},{1}'.format('ljy',24) print '{1},{0},{1}'.format('zju',120) #通过关键字参数 print '{name},{age}'.format(age = 18,name = "gebilaowang")
SocketServer是python提供的实现socket server的模块.利用其提供的api,可以很方便快速的开发一个socket服务器.整体上来说,模块提供了四个使用的类:
- TCPServer
- UDPServer
- UnixStreamServer
- UnixDatagramServer
上述的四个类都是同步的,即意味着当有请求过来后,其将同步处理数据,处理完之后才能处理下一个请求.
对于TCPServer
和UDPServer
来说,其在处理请求时,都是同步请求的.这意味着,只有一个请求处理完毕后,才能继续处理接下来的请求.如果请求处理需要很长时间,或者请求与Server之间有较多的交互,那同步处理就不大合适了.
在SocketServer模块中,提供了两种服务模型.
- ThreadingMixIn
- ForkingMixIn
顾名思义,ThreadingMixIn
代表其在有新的请求时,创建一个新的线程,在该线程中处理请求.相对应的,ForkingMixIn
表示在有新的请求时,创建一个新的进程,在该进程中处理请求.
对于该选择何种模型,可以考虑是否需要请求间数据共享.
#coding:utf-8 import socket import SocketServer import threading class ThreadTCPRequestHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request.recv(1024) cur_thread = threading.current_thread() response = "{}:{}".format(cur_thread.name,data) self.request.sendall(response) class ThreadTCPServer(SocketServer.ThreadingMixIn,SocketServer.TCPServer): pass def client(ip,port,message): sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.connect((ip,port)) try: sock.sendall(message) response = sock.recv(1024) print"received : {}".format(response) finally: sock.close() if __name__ == "__main__": HOST,PORT = "localhost",8888 server = ThreadTCPServer((HOST,PORT),ThreadTCPRequestHandler) ip,port = server.server_address #server_thread接收client请求 server_thread = threading.Thread(target = server.serve_forever) server_thread.daemon = True server_thread.start() print 'server loop running in thread:',server_thread.name for i in range(3): thread = threading.Thread(target = client,args = (ip,port,'hello world from{}'.format(i))) thread.start() print 'thread {} start'.format(i)
上述代码中,一个线程运行server,有多个客户端线程0,1,2,server接收客户端请求后,会创建新的线程来处理请求