python可以用来实现两个主机进程之间的TCP通信,就是通过使用socket套接字来实现的,我们可以基于此,来实现一些应用层协议,以达到不同主机之间的进程通信的目的。这一点,除了普通的网络应用程序(如聊天工具和游戏等)之外,在分布式系统中,也有着很大的用途,比如机器学习需要在多台计算机中进行并行计算的时候。
服务器/客户机模型(C/S模型)如图:
关于服务器模型
服务器模型主要有以下这两种:
1 循环服务器
即在任一时刻只处理一个客户机的请求,处理该请求的过程中,下一请求处于等待状态。
优点是节省服务器资源,缺点是响应时间长,适合处理非耗时的请求。
2 并发服务器
即并发执行,服务器每收到一个连接请求就创建一个进程(或线程)处理该连接,服务器继续等待下一连接。
优点是响应速度快,缺点是占用系统资源多。
演示实例:
多进程TCP并发服务
我们要使用到的包是socket和multiprocessing
服务器端:
首先使用socket对象的socket()方法获取一个套接字对象,再使用bind()方法绑定服务器端的IP地址和端口号,接着调用listen()方法开始监听,使用阻塞式的accept()方法获取每一个传入的客户端连接对象conn和信息。
当每收到一个客户端连接后,我们就创建一个进程来专门处理这个客户端连接,在python中可以将要创建进程的类从multiprocessing.Process父类中继承,在子类中的__init__()函数里传入启动进程时用到的参数并初始化配置,在run()函数中处理相关事情,在父进程中使用start()方法启动这个进程。
对于客户端的连接对象conn可以使用settimeout()方法设置超时时间,使用recv()方法接收客户端发来的数据,作为回应,可以使用sendall()方法回应客户端,给客户端发数据。
当我们不再需要客户端的时候,服务器端可以使用close()方法关闭该连接。
import multiprocessing import socket class ClientProcess(multiprocessing.Process): def __init__(self,conn,addr): multiprocessing.Process.__init__(self) self.conn = conn self.addr = addr def run(self): self.conn.sendall(bytes("你好,我是AI柠檬~",encoding="utf-8")) ret_timeout = str(self.conn.recv(1024),encoding="utf-8") self.conn.settimeout(int(ret_timeout)) while(True): try: ret = str(self.conn.recv(1024),encoding="utf-8") self.conn.sendall(bytes("我收到了你的信息:"+ret,encoding="utf-8")) if(ret==":q"): self.conn.close() break except Exception as ex: self.conn.close() break if __name__ == '__main__': s = socket.socket() inp_addr = input("Please input this server's ip address:\n>>>") inp_port = input("Please input this server's port:\n>>>") s.bind((inp_addr,int(inp_port))) s.listen() print("服务器已开启") users = [] while(True): conn,addr=s.accept() p = ClientProcess(conn,addr) p.start() users.append(p) print("有一个新用户连接,进程号pid:", p.pid) num = 0 tmp_users=[] for i in range(len(users)): if(users[i].is_alive()==True): tmp_users.append(users[i]) users = tmp_users print("当前用户数:", len(users)) s.close()
客户端:
同样,首先先使用socket对象的socket()方法获取一个套接字对象,然后使用connect()方法连接到指定IP地址和端口的服务器端程序。
其他如同服务器端,使用sendall()方法写出数据,使用settimeout()方法设置超时时间,使用recv()方法接收服务器端发来的数据。
当我们不再需要服务器端的时候,客户端可以使用close()方法关闭该连接。
import socket obj = socket.socket() inp_addr = input("Please input server's ip address:\n>>>") inp_port = input("Please input server's port:\n>>>") obj.connect((inp_addr,int(inp_port))) inp_timeout = input("Please input timeout(s):\n>>>") obj.sendall(bytes(inp_timeout,encoding="utf-8")) obj.settimeout(int(inp_timeout)) msg = str(obj.recv(1024),encoding="utf-8") print(msg) while True: inp = input("Please(:q\退出):\n>>>") if(inp!=""): obj.sendall(bytes(inp,encoding="utf-8")) if(inp == ":q"): obj.close() break try: ret = str(obj.recv(1024),encoding="utf-8") print(ret) except socket.timeout: print("[Error]Network Connection Time Out!") break except: print("[Error]Unknown Network Connection Error!") break
通过以上代码,就实现了不同主机上两进程间的socket套接字的TCP通信。由于Python的高度封装特性,我们所能做的很难涉及到底层,而且一般情况下也不需要涉及底层,除非我们有特殊需求。至于在做分布式的机器学习训练程序的设计和编程方法,就不是本文应该涉及的啦。
版权声明本博客的文章除特别说明外均为原创,本人版权所有。欢迎转载,转载请注明作者及来源链接,谢谢。本文地址: https://blog.ailemon.net/2018/01/21/python-implement-about-socket-connection/ All articles are under Attribution-NonCommercial-ShareAlike 4.0 |