最近做了一个多人聊天室项目,主要目的是练习和巩固socket编程。

在开始之前,可以先了解一下socket的TCP三次握手和四次挥手。

参考:https://blog.csdn.net/luoyoub/article/details/82348863?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159722038919724848337464%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=159722038919724848337464&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v3~pc_rank_v2-6-82348863.first_rank_ecpm_v3_pc_rank_v2&utm_term=Socket%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B&spm=1018.2118.3001.4187

下面是python的socket编程流程图:

首先,服务器端先创建一个socket,然后绑定ip和端口号,然后开始监听客户端的连接。

    #初始化方法(构造方法)
    def __init__(self):
        self.server = socket.socket()  #IPV4,TCP协议
        self.server.bind(("127.0.0.1",8989))  #绑定IP和端口号
        self.server.listen(5) #最大挂载数量是5个
        self.clients = []  #所有客户端
        self.clients_name_ip = {} #用户名字与ip的绑定信息

        #获得客户端连接
        self.get_conn()

监听状态之后,就是等待客户端的连接了。

    #监听客户端的连接
    def get_conn(self):
        while True:
            client,address = self.server.accept() #获取客户端的连接
            print(address)
            data = "与服务器连接成功!请你输入昵称才可以聊天"
            #server与client通信  send()必须encode  recv()必须decode
            client.send(data.encode())
            #将连接的用户添加到服务器的用户列表中
            self.clients.append(client)
            #服务器每接受到一个客户端连接,就启动一个线程
            Thread(target=self.get_msg, args=(client,self.clients,self.clients_name_ip,address)).start()

接受到客户端连接之后,启动线程,每个线程都是一个客户端,在这个线程里面再进行这个客户端的收与发

 #进行所有客户端消息处理
    def get_msg(self,client,clients,clients_name_ip,address):
        #接受客户端发来的昵称
        name = client.recv(1024).decode()
        #昵称与IP进行绑定
        clients_name_ip[address] = name
        #循环监听所有客户端的消息
        while True:
            #获取所有客户发送的消息
            try:
                recv_data = client.recv(1024).decode()
            except Exception as e:
                self.close_client(client,address)
                break
            #如果用户推出,输入Q
            if recv_data.upper() == "Q":
                self.close_client(client,address)
                break
            for c in clients:
                #谁在什么时候发送了什么消息
                c.send((clients_name_ip[address]+" "+time.strftime("%x")+"\n"+recv_data).encode())

如果客户端输入的是Q,那就关闭该客户端,并且告诉其他客户端,这个客户端已经离开了

    #关闭资源
    def close_client(self,client,address):
        self.clients.remove(client)
        client.close()

        print(self.clients_name_ip[address]+"已经离开了")
        for c in self.clients:
            c.send((self.clients_name_ip[address]+"已经离开了").encode())

接下来是客户端,首先要写一个客户端的窗口,然后,客户端要与服务器取得连接

    #初始化界面
    def __init__(self):
        QWidget.__init__(self)
        #设置窗口的大小与位置
        self.setGeometry(600,300,360,300)
        #设置标题
        self.setWindowTitle("聊天室")
        #添加背景
        palette = QtGui.QPalette()
        bg = QtGui.QPixmap(r"./img/background.jpg")
        palette.setBrush(self.backgroundRole(),QtGui.QBrush(bg))
        self.setPalette(palette)
        self.add_ui()
        #与服务器连接
        self.client = socket.socket()
        self.client.connect(("127.0.0.1",8989))
        self.work_thread()

然后分别开启两个线程,收信息的线程,和发信息的线程

    #线程处理
    def work_thread(self):
        Thread(target=self.btn_send).start()
        Thread(target=self.recv_msg).start()

下面是客户端发送消息

    #发送消息
    def send_msg(self):
        msg = self.message.text()
        self.client.send(msg.encode())
        if msg.upper()=="Q":
            self.client.close()
            self.destroy()
        self.message.clear()

客户端接受消息,要循环着一直接受

    #接受消息
    def recv_msg(self):

        while True:
            try:
                data = self.client.recv(1024).decode()
                print(data)
                data = data + "\n"
                self.content.append(data)
            except:
                exit()

到这里,主要的逻辑几乎就完成了,客户端之间可以通过服务器中转,互相发送消息

有需要讨论的,或者需要源码的小伙伴,可以留言联系我哟~

Logo

致力于链接即构和开发者,提供实时互动和元宇宙领域的前沿洞察、技术分享和丰富的开发者活动,共建实时互动世界。

更多推荐