利用python实现TCP和UDP服务器

  利用python的socket模块可以实现基本的网络编程,并且只限于一对一的连接。当然,也可以在其基础上实现一个网络服务器,但由于太底层这种做法不被推荐。其实如果要实现一个网络服务器很简单,调用python的内置模块socketserver就够了。

server类

  socketserver模块下面有四种套接字server类:TCPserverUDPServerUnixStreamServerUnixDatagramServer。前两种分别为使用TCP和UDP协议的server类,后两种用法和前面一样但只限于unix类系统。它们的参数都一样,如下:

TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)
  • 参数server_address: IP地址和端口,为一个元组如: ("127.0.0.1", 8000)
  • 参数RequestHandlerClass: 一个自定义的handle类,主要负责实现连接到来时所要执行的操作。后面会介绍怎么自定义。
  • 参数bind_and_activate: 默认为True。如果设置为False,代表你得手动操作底层的socket,这样会更加灵活。

前面的四种类都继承自一个BaseServer类,实现了基本方法和属性:

  • fileno(): 返回一个服务器正绑定的socket文件描述符。
  • handle_requeset(): 处理一个请求。依次执行 get_request(), verify_request(), 和 process_request() 方法。用户自定义的handleclass下的handle方法抛出异常,服务器的handle_error()会被调用。
  • server_forever(poll_interval=0.5): 进入一个循环, 一直接收并处理请求直到一个显示的 shutdown() 请求到来。默认每隔0.5秒轮询(pull)一次。
  • shutdown(): 告诉server_forever()得到的循环结束循环。
  • server_address(): 返回正在监听的IP和端口,如:("127.0.0.1", 80)
  • socket: 正使用的socket对象
  • socket_type: socket类型,通常为:socket.SOCK_STREAM和socket.SOCK_DGRAM
  • timeout: 超时时间。

请求处理类

  通常需要继承BaseRequestHandler,并重写hanle()方法。当一个网络请求被创建时,一个新的实例就会被创建。

 class socketserver.BaseRequestHandler

  方法如下:

  • setup(): 在handle()被调用前被执行,一般用于一些初始化操作。默认不执行任何操作。
  • handle(): 当一个请求到来后,用户所要执行操作,这个方法应该被重写,操作self.request。
  • finish(): handle之后调用的函数,用于执行一个清理工作。

server代码如下:

 1 import socketserver
 2 
 3 class echorequestserver(socketserver.BaseRequestHandler):
 4     def handle(self):
 5         print('服务端启动...')
 6         conn = self.request
 7         print('获得连接:', self.client_address)
 8         while True:
 9             client_data = conn.recv(1024)
10             if not client_data:
11                 print('断开连接')
12                 break
13             print(client_data.decode('utf-8'))
14             print('开始发送...')
15             conn.sendall(client_data)
16             
17 if __name__ == '__main__':
18     server =socketserver.TCPServer(("127.0.0.1", 8000),echorequestserver)  # 使用处理单连接的TCPServer
19     server.serve_forever()

客户端代码如下:

 1 import socket,time
 2 
 3 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 4 s.connect(('127.0.0.1',8000))
 5 
 6 while True:
 7     st = input('input command: ')
 8     if not st:break
 9     s.send(st.encode('utf-8'))
10     
11     echo_back = s.recv(1024)
12     print(echo_back.decode('utf-8'))
13  
14 s.close()

 

  当然,以上例子是用于单线程的情况。如果想同时接收多个连接,可以换成ThreadingTCPServer,用法和上面完全一样。不过这种情况下,建议使用线程池以避免突然面临多个连接同时到来的情况。

posted on 2017-03-14 14:42  科幻vs现实  阅读(10777)  评论(0编辑  收藏  举报

导航