昨天定了篇关于《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函数也可以只写成一个循环的形式,不用多线程。




评论