'''
1.创建监听套接字
2.循环等待客户端连接
3.客户端连接创建新的进程为客户端服务
4.原进程继续等待其他客户端连接
5.客户端退出,对应的进程也销毁
'''from socket import*import os
import signal
HOST ='0.0.0.0'
PORT =8888
ADDR =(HOST,PORT)#处理僵尸进程
signal.signal(signal.SIGCHLD,signal.SIG_IGN)#处理客户端具体交互的函数defhandle(c):
whileTrue:
data = c.recv(1024)ifnot data:breakprint(data.decode())#给客户端回信息
c.send(b'OK')
c.close()#创建套接字
s = socket()#设置套接字选项,让端口能立即重用
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.listen(5)#该参数在linux下不管用,linux内核自己有#循环等待客户端连接print('Listen the port 8888....')whileTrue:#循环等待客户端连接try:
c,addr = s.accept()print('Connect from',addr)except KeyboardInterrupt as e:#从终端ctrl+c退出
os._exit(0)except Exception as e:print(e)continue#创建进程
pid = os.fork()#如果创建进程出错,继续等待下一个客户端连接(其实和父进程的流程一样)if pid <0:#将之前创建出来的连接套接字c释放掉,释放掉资源占用
c.close()#如果进程创建成功,和客户端进行交互,交互结束后子进程立即结束 elif pid ==0:#子进程其实只是负责和客户端交互(连接套接字c有用,监听套接字s没用),所以将子进程中的s套接字释放掉(因为子进程完全复制父进程的内存空间)
s.close()
handle(c)#和客户端交互,将连接套接字传进去
os._exit(0)#客户端结束后,子进程结束(销毁),而父进程不会退出,这是典型的产生僵尸进程的场景,而且越积累越多,所以用signal处理#原进程继续等待下一个客户端连接 else:
c.close()#因为父进程中其实只是负责接收连接(s监听套接字),负责处理具体请求的连接套接字c其实是没用的,而且占用资源 ,所以关掉
客户端
from socket import*#创建tcp套接字
sockfd = socket()#默认值#连接服务器
server_addr =('127.0.0.1',8888)#服务器地址
sockfd.connect(server_addr)#发收消息whileTrue:
msg =input('Msg:')ifnot msg:break
sockfd.send(msg.encode())#字节串
data = sockfd.recv(1024)print('From server:',data.decode())
用客户端测试服务端大概可承受多少进程并发
from socket import*
n =0#用n记录并发个数whileTrue:#创建tcp套接字
sockfd = socket()#默认值#连接服务器
server_addr =('127.0.0.1',8888)#服务器地址
sockfd.connect(server_addr)
n +=1print(n)