网络编程实验四

实现一个可以同时多人在线的网络聊天室软件

一、设计思路,程序流程图

1) 用户通过用户名,密码登录聊天室
2) 在每一条聊天内容之前,显示发出这条聊天内容的用户名。
3) 聊天室可以用web,客户端,或者手机APP方式实现。
流程图如下:
在这里插入图片描述

二、程序源代码

#客户端程序client.py  
  
from tkinter import *  
import tkinter.font as tkFont  
import datetime  
import time  
import threading  
import socket  
  
global name  
global entry_room  
data = {'张三':'10000','李四':'10001','王五':'10002'}  
entry_room=0  
  
def Sign():  
      
    def Check():  
        global name,entry_room  
        num = num_entry.get()  
        pawd = pawd_entry.get()  
        if num in data:  
            if pawd == data[num]:
                #msgbox.showinfo('温馨提示', '成功登录')
                
                if(enterroom()):
                    print("成功登录")               
                    name = num+': '
                    entry_room = 1
                    top.destroy()

                else:
                    #print("登录失败")
                    msgbox.showinfo('温馨提示', '登录失败')
                
            else:
                #print("密码错误")
                msgbox.showinfo('温馨提示', '密码错误')
        else:
            msgbox.showinfo('温馨提示', '用户不存在')
            #print("用户不存在")


    def enterroom():
        try:
            udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
            #绑定本地信息
            udp_socket.bind(('127.0.0.1',10000))
            udp_socket.sendto('login'.encode('utf-8'),('127.0.0.1',9999))
            recv_data = udp_socket.recvfrom(1024)
            if(recv_data):
                #print(recv_data)
                udp_socket.close()
                return 1
        except:
            udp_socket.close()
            return 0  
      
    top = Tk()  
    top.title("登录界面")  
  
    frame_sign = Frame(width=285, height=115)  
    ft = tkFont.Font(family='NSimSun', size=13)  
  
    label_num = Label(frame_sign,text='账号:',font=ft)  
    label_pawd = Label(frame_sign,text='密码:',font=ft)  
    num_entry = Entry(frame_sign,font=ft)  
    pawd_entry = Entry(frame_sign,font=ft)  
    button_sign = Button(frame_sign,text='登录',font=ft,command=Check)  
    button_quit = Button(frame_sign,text='退出',font=ft,command=top.destroy)  
  
    frame_sign.grid(row=0, column=0,padx=4, pady=0)  
  
    label_num.place(x=10,y=7)  
    label_pawd.place(x=10,y=45)  
    num_entry.place(width=200,height=25,x=70,y=7)  
    pawd_entry.place(width=200,height=25,x=70,y=45)  
    button_sign.place(width=80,height=25,x=50,y=80)  
    button_quit.place(width=80,height=25,x=150,y=80)  
  
    top.mainloop()  
  
  
def Chatroom():  
      
    def record_clear():  
        text_msglist.delete('0.0',END)  
        #success = '- - - - - - - - - - - - - - - -  正  在  聊  天  - - - - - - - - - - - - - - - -'  
        #text_msglist.insert(END,success)  
  
  
    def recv_msg(udp_socket,text_msglist):  
        while 1:  
            recv_data = udp_socket.recvfrom(1024)  
            recv_msg = recv_data[0].decode('utf-8')  
            time_now = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+'\n'  
            text_msglist.insert(END,time_now)  
            text_msglist.insert(END,recv_msg+'\n\n')  
            text_msglist.see(END)  
  
  
    def start_recv():  
        t_recv = threading.Thread(target = recv_msg,args = (udp_socket,text_msglist))  
        #接收信息  
        t_recv.start()  
  
  
    def msg_clear():  
        global name  
        #global dest_ip,dest_port      
        send_data = text_msg.get('0.0',END)  
        if(send_data!='\n'):  
            #time_now = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+'\n'  
            #text_msglist.insert(END,time_now)  
            #text_msglist.insert(END,'我:'+send_data+'\n')  
            send_data = name+send_data  
            udp_socket.sendto(send_data.encode('utf-8'),('127.0.0.1',9999))  
            text_msg.delete('0.0',END)  
            text_msglist.see(END)  
  
  
    #创建套接字  
    udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  
    udp_socket.sendto('newconn'.encode(‘utf-8))
    #绑定本地信息  
    udp_socket.bind(('127.0.0.1',10000))  
      
  
    root = Tk()  
    root.title('聊天室界面')  
  
       
    #创建几个frame作为容器  
    frame_left_top   = Frame(width=565, height=310, bg='white')  
    frame_left_center  = Frame(width=565, height=100, bg='white')  
    frame_left_bottom  = Frame(width=565, height=34, bg='white')  
  
  
    ##创建需要的几个元素  
    text_msglist = Text(frame_left_top)  
    success = '- - - - - - - - - - - - - - - -  加  入  成  功  - - - - - - - - - - - - - - - -'  
    text_msglist.insert(END,success)  
    start_recv()  
      
    text_msg = Text(frame_left_center)  
    button_sendmsg = Button(frame_left_bottom,text='发 送 信 息',command=msg_clear)  
    button_msgclear = Button(frame_left_bottom,text='删除聊天记录',command=record_clear)  
  
    #使用grid设置各个容器位置  
    frame_left_top.grid(row=0, column=0, padx=4, pady=5)  
    frame_left_center.grid(row=1, column=0, padx=4, pady=0)  
    frame_left_bottom.grid(row=2, column=0,padx=4, pady=0)  
  
    frame_left_top.grid_propagate(0)  
    frame_left_center.grid_propagate(0)  
    frame_left_bottom.grid_propagate(0)  
  
  
    #把元素填充进frame  
    text_msglist.grid()  
    text_msg.grid()  
    button_sendmsg.place(width=150,height=30,x=410,y=0)  
    button_msgclear.place(width=160,height=30,x=4,y=0)  
  
  
    #主事件循环  
    root.mainloop()  
  
  
def main():  
    global entry_room  
    #entry_room = 0  
    Sign()  
    if entry_room:  
        Chatroom()  
        print("退出聊天室")  
  
if __name__ == '__main__':  
    main()

#服务器程序serve.py
import socket  
  
allusers=[]  
  
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  
server.bind(('127.0.0.1', 9999))  
  
while True:  
    recv_data = server.recvfrom(1024)  
    txtdata = recv_data[0]  
    if recv_data[1] not in allusers:  
        allusers.append(recv_data[1]) 
    if txtdata!=b'newconn': 
        for i in allusers:  
            server.sendto(txtdata,i)

三、实验运行结果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值