Python网络编程(一) 使用SocketServer.ForkingMixIn类的套接字服务器示例

实现方式是通过继承SocketServer.ForkingMixIn与SocketServer.TCPServer类,使用TCPServer类可以让套接字server端不需要手动实现创建套接字实例,绑定地址,进入监听模式等操作,继承ForkingMixIn类来处理异步客户端。

 

 1 # socket test with ForkingMixIn class
 2 
 3 import os
 4 import socket
 5 import SocketServer
 6 import threading
 7 # from multiprocessing import Process
 8 
 9 SERVER_HOST = "localhost"
10 SERVER_PORT = 0 # indicat to use dyminic port
11 BUF_SIZE = 1024
12 ECHO_MSG = "Hello echo server"
13 
14 
15 class ForkingClient():
16     """a client to use forking server """
17     def __init__(self, ip, port):
18         self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
19         self.sock.connect((ip, port))
20     
21     def run(self):
22         """ client send infor to server """
23         # get current client's ip 
24         current_process_id = os.getpid()
25         print "PID %s sending echo messages to server: %s" % \
26             (current_process_id, ECHO_MSG)
27         # use sock.send() to get length
28         sent_data_length = self.sock.send(ECHO_MSG)
29         print "%s characters sent so far..." % sent_data_length
30 
31         # get the server response
32         s_response = self.sock.recv(BUF_SIZE)
33         # disp the server response, split s_response
34         print "PID %s received: %s" % ( current_process_id, s_response[5:] )
35 
36     def clientshutdown(self):
37         self.sock.close()
38 
39 # def server's handle mthd
40 class ForkingServerRequestHandler(SocketServer.BaseRequestHandler):
41     def handle(self):
42         # get echo from client, notice "request.recv()"
43         data = self.request.recv(BUF_SIZE)
44         current_process_id = os.getpid()
45         s_response = '%s: %s' % ( current_process_id,  data)
46         # send echo back to client
47         print "Server sending back [current_process_id: data] %s" % \
48             s_response
49         # use .request.send() mthd
50         self.request.send(s_response)
51         # use return
52         return
53 
54 class ForkingServer(SocketServer.ForkingMixIn, SocketServer.TCPServer):
55     """ just inherit everything from parents """
56     pass
57 
58 def main():
59     # build the server like TCPServer initiate 
60     server = ForkingServer( (SERVER_HOST, SERVER_PORT), ForkingServerRequestHandler)
61 
62     ip, port = server.server_address # get server's ip and port
63     # serve_forever Handle requests until an explicit shutdown() request. 
64     server_thread = threading.Thread(target=server.serve_forever)
65     server_thread.setDaemon(True)
66 
67     # server start
68     server_thread.start()
69     #server_thread.join()
70     print "Server loop runing PID: %s" % os.getpid()
71 
72     # build client and start
73 
74     client1 = ForkingClient(ip, port) # use server's ip and port
75     client1.run()
76 
77     client2 = ForkingClient(ip, port)
78     client2.run()
79 
80     # clean
81     server.shutdown()
82     client1.clientshutdown()
83     client2.clientshutdown()
84     server.socket.close()
85 
86 if __name__ == '__main__':
87     main()

 


注意点1:

初次在Windows上运行时报错如下, 在帮助文档查询到os.fork只能运行在unix平台:

报错如下:

File "C:\Python27\lib\SocketServer.py", line 556, in process_request:

pid = os.fork()

AttributeError: 'module' object has no attribute 'fork'

os.fork()说明:  

Fork a child process. Return 0 in the child and the child’s process id in the parent. If an error occurs OSError is raised.Note that some platforms including FreeBSD <= 6.3, Cygwin and OS/2 EMX have known issues when using fork() from a thread.

Availability: Unix

注意点2:

在main块执行完SERVER和CLIENT的发送及接受后,SERVER执行了shutdown()后又执行socket.close(),为什么要这么做?

shutdown()关闭读写的连接并发送Fin/EOF 信号给所有的节点,而不管有多少进程连接在SERVER上,但是它不释放连接,所以再调用close()来释放

 

posted on 2016-11-04 15:42  slowstatic  阅读(1764)  评论(0)    收藏  举报