《老鸟python 系列》视频上线了,全网稀缺资源,涵盖python人工智能教程,爬虫教程,web教程,数据分析教程以及界面库和服务器教程,以及各个方向的主流实用项目,手把手带你从零开始进阶高手之路!点击 链接 查看详情




多线程聊天

阅读:211168782    分享到

前面我们写了个服务器和客户端聊天的通信程序,一个服务器对应一个客户端,但是,通常情况下,服务器可以对应多个客户端,传统的 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等模型。

上面的例子,我们只是一个简单的举例,本章学完后,我们要写一个聊天室程序,这个时候的服务器起到对聊天室内的客户端进行信息转发的作用,大家可以试着先写一个简单的聊天室程序。

作业

重写一遍多线程聊天代码,并跑通程序。


如果以上内容对您有帮助,请老板用微信扫一下赞赏码,赞赏后加微信号 birdpython 领取免费视频。


登录后评论

user_image
feemung
2020年1月28日 07:47 回复

有图有真相,写得真好,谢谢博主


user_image
火鸡味锅巴
2019年6月1日 05:45 回复

看懂了!


user_image
justjavac
2019年3月30日 21:39 回复

有让人恍然大悟之感,感谢


user_image
范德林德第一劳模
2019年2月8日 12:57 回复

终于可以写聊天程序了,我准备写个聊天室瞒着我媳妇,给我女朋友用


user_image
杨扬
2018年11月28日 23:46 回复

我准备写个聊天室,给我同学用~~