预计所需阅读时间:5分钟
昨天定了篇关于《Windows系统下Python编码的问题与解决方法》,讲的是编码的问题。今天要讲Python在Windows系统下第二问题,多线程问题。面目前来看,其实Windows下Python编程多出来的问题,主要这两个:编码与多线程。
在使用用Socket来编程时,会出现OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次
,这样的提示
import socket import multiprocessing def send(new): data = new.recv(1024) print(data.decode("gbk")) def main(): tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp.bind(("", 7890)) tcp.listen() print("*"*30) while True: new, address = tcp.accept() print("连接成功") p = multiprocessing.Process(target=send, args=(new, )) p.start() new.close() tcp.close() main()
原因是在Windows中因为子进程会复制主进程中所有代码,导致相同的端口在子进程中同样被绑定同样的端口,解决办法是程序最后做一个判断:
if __name__ == '__main__': main()
因此,也不能用os.fork()来创创建子进程。而在Linux系统下可以fork,新建的子进程与父进程使用不同的进程号PID。
还有在使用进程池的时候,也一定要加这上这句判断,否则子进程会递归的添加进程到进程池形成死循环。
如果使用多线程池来写Socket TCP服务可以改写成这种形成:
# coding:utf-8 import os from socket import socket, AF_INET, SOCK_STREAM from multiprocessing import Pool from threading import Thread def server(client): print("server_pid=", os.getpid()) def chat(client): while True: try: message = client.recv(1024) except: break else: print(message.decode("utf-8")) # 空字符串跳过 if not message: continue if message == "quit": print("close") client.close() break else: print("send") ack_message = "\r\n %s received..." % str(os.getpid()) client.send(bytes(ack_message, encoding="utf-8")) t = Thread(target=chat, args=(client,)) t.start() if __name__ == "__main__": s_server = socket(AF_INET, SOCK_STREAM) s_server.bind(("127.0.0.1", 8000)) s_server.listen() p = Pool(3) while True: client, addr = s_server.accept() print(client) p.apply(server, args=(client,))
在服务器端中使用多线程池,来连接不同的客户端,里面的server函数也可以只写成一个循环的形式,不用多线程。
评论