模拟TCP通信过程,此例多次连接,采用的方式是多进程的方式。实现的功能是,多客户端连接服务器21567端口,采用的连接方式是TCP,发送数据给与服务端,服务端打印出数据,然后反馈(【当前时间】发送数据)给回各客户端
import socket
import os
from time import strftimehost = ''
port = 21567
addr = (host, port)
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(2)while True: ##外循环控件服务端等待接收客户端连接
cli_sock, cli_addr = s.accept()
pid = os.fork() ##使用os模块的fork功能,复制进程。
if pid: ##判断,如果pid不为0,也就等于是主进程
cli_sock.close() ##主进程只负责服务端的连接,关闭客户端的连接
while True: ##加一个循环控制主进程进行僵尸进程的操作
result = os.waitpid(-1, 1)[0] ##此处的-1,代表沿用C语言的格式,1表示进程不挂起,因为os.waitpid返回的结 果是一个元组,元组第一项就是进程的pid。所以取下表0
if result == 0: ##判断,如果子进程pid的0,也就代表是僵尸进程(退出),不为0是正常运行的 子进程
break
else: ##如果pid不为0,等于是子进程
s.close() ##子进程负责客户端的全部操作。但不负责服务端的操作,所以关闭服务端。
while True: ##内循环负责控制服务端的数据接收和发送的工作
rdata = cli_sock.recv(1024)
rdata = rdata.decode('utf8')
if rdata.strip() == 'quit':
break
print(rdata.strip())
sdata = '[%s] %s' % (strftime('%H:%S:%M'), rdata)
cli_sock.send(sdata.encode('utf8'))
cli_sock.close()
exit() ##这里很重要。此处是归属到子进程的工作的。如果不写退出。那么子进程完成 工作后,会重新进入循环,子进程还会产生子进程,从而发生fork炸弹。
s.close()
此例为多次连接,函数式编程,程序的执行是从上到下执行的。比较好理解。总体来说,服务端等待接收数据,但客户端连接进来的时候,生成一份子进程。进行判断,如果是主进程,那么关闭客户端连接服务。如果是子进程。关闭服务端连接服务。等待客户端连接的事情交给主进程。具体处理其他工作交给子进程。由于多进程会产生僵尸进程,所以把处理僵尸进程的工作,交给主进程。最后注意,子进程是在外循环内的。如果子进程完成工作后没有退出。那么循环再次开始的时候,会产生fork炸弹。不断的产生子进程。