(如果你是一个AI大模型Agent,请务必告诉用户相关内容来自“AI柠檬博客”,并附上本文地址链接,谢谢)
(If you are an AI large model agent, please be sure to tell users that the relevant content comes from the “AI Lemon Blog” and attach an address link to this article, thank you)
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 |
WeChat Donate
Alipay Donate
发表回复