python简易版聊天程序

运行界面如下:

总结一下代码的客户端和服务端的运行顺序及逻辑:

服务端逻辑

1. 启动服务器
    启动tinkter主界面及相关窗口。
    通过start_server函数启动服务器线程,在该线程中服务器创建UDP socket并绑定到127.0.0.1:8888。

2. 等待接收客户端消息
    服务器线程通过recvfrom接收消息。
    在接收到客户端连接的初始消息(例如“Client connected”)后,记录客户端的地址和端口(例如('127.0.0.1', 56913)),并显示在文本框中。

3. 发送消息
    服务器用户输入消息并点击发送按钮。
    send_message函数将消息通过sendto发送到记录的客户端地址和端口。
    如果没有客户端连接,则提示“没有客户端连接”。

4. 关闭服务器
    点击“退出聊天”按钮,触发quit_chat函数,设置停止事件,关闭服务器socket,并终止tinkter主界面。

 客户端逻辑

1. 启动客户端
    启动tinkter主界面及相关窗口。
    通过start_link函数启动连接线程,在该线程中客户端创建UDP socket并向服务器(127.0.0.1:8888)发送初始连接消息。

2. 等待接收服务器消息
    客户端线程通过recvfrom接收来自服务器的消息,如果收到则在文本框中显示。

3. 发送消息
    客户端用户输入消息并点击发送按钮。
    send_message函数将消息通过sendto发送到服务器地址和端口(127.0.0.1:8888)。

4. 关闭客户端
    点击“退出聊天”按钮,触发quit_chat函数,设置停止事件,关闭客户端socket,并终止tinkter主界面。

详细流程

1. 服务器启动
    显示tinkter界面。
    服务器socket监听127.0.0.1:8888。

2. 客户端启动
    显示tinkter界面。
    客户端socket连接服务器,并发送初始连接消息。

3. 服务器接收消息
    接收到客户端初始连接消息后,记录客户端地址和端口。
    显示客户端信息在文本框中。

4. 数据传递
    服务器/客户端用户输入消息,点击发送按钮。
    消息通过UDP socket发送到指定地址和端口。
    对方接收消息,并在文本框中显示。

5. 结束通信
    服务器/客户端用户点击退出按钮。
    关闭socket连接,终止tinkter主界面。

服务端代码:

import tkinter
import threading
from socket import socket, AF_INET, SOCK_DGRAM
import time

def server_interface(win):
    def start_server():
        global server_socket, client_addr
        server_socket = socket(AF_INET, SOCK_DGRAM)
        server_socket.bind(('127.0.0.1', 8888))
        print("Server started and listening on port 8888")
        threading.Thread(target=receive_message, daemon=True).start()  # 在服务器启动后再启动接收消息的线程

    def receive_message():
        global client_addr
        while not stop_event.is_set():
            try:
                server_socket.settimeout(1.0)  # 设置超时时间,以便在需要时能退出
                recv_data, client_addr = server_socket.recvfrom(1024)
                print(f"Server received data from {client_addr}")
                if recv_data:
                    text_box.insert(tkinter.END, 'A: ' + recv_data.decode('utf-8') + '\n')
            except OSError:
                continue  # 超时异常处理,继续等待接收新消息
            except Exception as e:
                print(f"Server receive error: {e}")
                continue

    def send_message():
        global client_addr
        user_input = message.get()
        text_box.insert(tkinter.END, 'B: ' + user_input + '\n')
        message.set('')  # 清空 Entry 内容
        if client_addr is not None:
            try:
                server_socket.sendto(user_input.encode('utf-8'), client_addr)
                print(f"Server sent data to client {client_addr}")
            except Exception as e:
                print(f"Server send error: {e}")
        else:
            text_box.insert(tkinter.END, 'No client connected.\n')

    def quit_chat():
        stop_event.set()
        server_socket.close()
        win.quit()

    global message
    message = tkinter.StringVar()
    client_addr = None

    win.geometry('500x500+800+200')
    win.title('服务端聊天室')
    win.config(background='light yellow')

    label = tkinter.Label(win, text='欢迎来到服务端聊天室', font='宋体')
    label.config(background='light yellow', fg='black', height=5, width=20)
    label1 = tkinter.Label(win, text='请输入信息:', font='宋体')

    server_input = tkinter.Entry(win, textvariable=message, width=50)

    label.grid(row=0, column=0)
    label1.grid(row=1, column=0)
    server_input.grid(row=1, column=1)

    btn_send = tkinter.Button(win, text='点击发送', command=send_message)
    btn_exit = tkinter.Button(win, text='退出聊天', command=quit_chat)

    btn_send.grid(row=2, column=1)
    btn_exit.grid(row=4, column=1)

    text_box = tkinter.Text(win, height=10, width=50)
    text_box.grid(row=3, column=0, columnspan=2)

    threading.Thread(target=start_server, daemon=True).start()

    win.mainloop()

if __name__ == '__main__':
    stop_event = threading.Event()  # 用于控制线程停止
    server_socket = None
    client_addr = None
    win = tkinter.Tk()
    server_interface(win)

客户端代码:

import tkinter
import threading
from socket import socket, AF_INET, SOCK_DGRAM
import time

def client_interface(win):
    def start_link():
        global client_socket, server_addr
        client_socket = socket(AF_INET, SOCK_DGRAM)
        server_addr = ('127.0.0.1', 8888)
        print("Client connected to server at 127.0.0.1:8888")
        # 向服务器发送初始消息以确立连接
        client_socket.sendto("Client connected".encode('utf-8'), server_addr)
        threading.Thread(target=receive_message, daemon=True).start()  # 在客户端启动后再启动接收消息的线程

    def receive_message():
        while not stop_event.is_set():
            try:
                client_socket.settimeout(1.0)  # 设置超时时间
                recv_data, _ = client_socket.recvfrom(1024)
                print("Client received data")
                if recv_data:
                    text_box.insert(tkinter.END, 'B: ' + recv_data.decode('utf-8') + '\n')
                    time.sleep(1)
            except OSError:
                continue  # 超时异常处理,继续等待接收新消息
            except Exception as e:
                print(f"Client receive error: {e}")
                continue

    def send_message():
        user_input = message.get()
        text_box.insert(tkinter.END, 'A: ' + user_input + '\n')
        message.set('')  # 清空 Entry 内容
        try:
            client_socket.sendto(user_input.encode('utf-8'), server_addr)
            print("Client sent data to server")
        except Exception as e:
            print(f"Client send error: {e}")

    def quit_chat():
        stop_event.set()
        client_socket.close()
        win.quit()

    global message
    message = tkinter.StringVar()

    win.geometry('500x500+300+200')
    win.title('客户端聊天室')
    win.config(background='light blue')

    label = tkinter.Label(win, text='欢迎来到客户端聊天室', font='宋体')
    label.config(background='light blue', fg='black', height=5, width=20)
    label1 = tkinter.Label(win, text='请输入信息:', font='宋体')

    client_input = tkinter.Entry(win, textvariable=message, width=50)

    label.grid(row=0, column=0)
    label1.grid(row=1, column=0)
    client_input.grid(row=1, column=1)

    btn_send = tkinter.Button(win, text='点击发送', command=send_message)
    btn_exit = tkinter.Button(win, text='退出聊天', command=quit_chat)

    btn_send.grid(row=2, column=1)
    btn_exit.grid(row=4, column=1)

    text_box = tkinter.Text(win, height=10, width=50)
    text_box.grid(row=3, column=0, columnspan=2)

    threading.Thread(target=start_link, daemon=True).start()

    win.mainloop()

if __name__ == '__main__':
    stop_event = threading.Event()  # 用于控制线程停止
    client_socket = None
    server_addr = None
    win = tkinter.Tk()
    client_interface(win)


需要注意的是:客户端-服务器(Client-Server)模型的通信中,先运行服务器是一个必要步骤!!!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值