前面我们写了个服务器和客户端聊天的通信程序,一个服务器对应一个客户端,但是,通常情况下,服务器可以对应多个客户端,传统的 C/S(服务器/客户端)项目,一般情况下是一个服务器对应多个客户端,服务器起到服务多个客户端的作用。
我们使用最多的 C/S 架构的通信项目有 QQ。我们本机上使用的 QQ 是客户端,服务器在腾讯公司,我们 QQ 之间互相聊天,服务器起到转发一个 QQ 客户端信息到另一个 QQ 客户端的作用。
当然,还有一些聊天室类的程序,服务器起到转发一个聊天室内用户信息到聊天室内所有用户的作用。
本节课,我们先写一个简单的 C/S 结构的聊天程序,当然,我们这个聊天程序,并不是服务器转发客户端信息,我们的服务器可以和多个客户端进行“同时”(并发)聊天。
服务器端的套接字起到监听的作用(类似电话主机),每连接成功一个客户端,就返回一个和客户端通信的套接字(类似电话的分机),服务器端用每个“分机”和每个客户端进行通信。
因为我们使用的是默认的阻塞套接字,服务器和每个客户端通信的过程都是阻塞的,所以,为了服务器可以“同时”(并发)和客户端进行通信,我们用到了多线程,我们把服务器和客户端的通信逻辑写在函数 tcplink 里面,然后,每个和客户端通信的线程去调用它。
''' 此为服务器程序 ''' import socket import threading def tcplink(sock, addr): # 和每个客户端通信的逻辑 print('新客户端连接到来:%s:%s' % addr) while True: client_data = sock.recv(1024).decode("utf-8") # 接收信息 if (client_data == "exit") or (not client_data): # 判断客户端是否申请结束会话或客户端是否退出 break print("收到客户端信息:%s" % client_data) server_data = input("请输入要发送给客户端的信息:") sock.send(server_data .encode("utf-8")) # 发送信息 sock.close() # 关闭和客户端通信的套接字 sv_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建套接字 sv_ipport = ("0.0.0.0", 8889) # 监听的 ip 和端口 sv_socket.bind(sv_ipport) # 绑定服务地址 sv_socket.listen(5) # 协议栈缓冲区最大套接字存放个数 print('启动服务器,等待客户端连接......') while True: server_socket, addr = sv_socket.accept() t = threading.Thread(target=tcplink, args=(server_socket, addr)) t.start() # 每个客户端对于一个服务器线程 server_socket.close() # 关闭监听的服务器套接字
同学们可以启动多个客户端程序,然后可以用每个客户端和服务器进行通信,你会发现,服务器可以“同时”(并发)服务多个客户端。
''' 此为客户端程序 ''' import socket client_socket = socket.socket() # 创建套接字 ip_port = ("127.0.0.1", 8889) # 要连接的服务器的 ip 和端口 client_socket.connect(ip_port) # 连接服务器 while True: client_data = input("请输入要发送给服务器的信息:") # 输入内容的长度请大于 2 client_socket.send(client_data.encode("utf-8")) # 发送信息 server_data = client_socket.recv(1024).decode("utf-8") # 接收信息 if (server_data == "exit") or (not server_data): # 判断服务器是否申请结束会话或客户端是否退出 break print("收到服务器信息:%s" % server_data) client_socket.close() # 关闭套接字
服务器实现并发的技术方案有很多,纯粹的使用多线程一般只适合于学习,实际项目中我们更多的使用线程池(appache),还有单线程异步轮询(nginx,tornado,node.js等等),单线程异步轮询是主流,基于异步轮询的网络模型有 select,poll,epoll等模型。
上面的例子,我们只是一个简单的举例,本章学完后,我们要写一个聊天室程序,这个时候的服务器起到对聊天室内的客户端进行信息转发的作用,大家可以试着先写一个简单的聊天室程序。
重写一遍多线程聊天代码,并跑通程序。
有图有真相,写得真好,谢谢博主