服务器之家

服务器之家 > 正文

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

时间:2021-08-30 00:16     来源/作者:aaaadioppa

实验名称:

网络聊天室

功能:

i. 掌握利用socket进行编程的技术
ii. 掌握多线程技术,保证双方可以同时发送
iii. 建立聊天工具
iv. 可以和单人聊天
v. 可以和多个人同时进行聊天
vi. 使用图形界面,显示双方的语录
vii. 程序可以在一定程度上进行错误识别

概述

实验通过聊天室可以完成单人或多人之间的聊天通信,功能的实现主要是通过socket通信来实现。本次实验采用客户端/服务器(c/s)架构模式,通过python语言来编写服务器端与客户端的程序。运用多线程可完成多点对多点的聊天。
服务器端程序主要用于接收用户信息,消息接收与转发。
客户端程序实现用户注册登录,聊天信息显示与信息输入。

代码解释

统计当前在线人数,并且将新用户加到用户列表中。
serve.py

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

这是服务器对于聊天服务的实现。

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

通过继承threading.thread类而实现多线程,重写run函数。

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

接受来自客户端的用户名,如果用户名为空,使用用户的ip与端口作为用户名。如果用户名出现重复,则在出现的用户名依此加上后缀“2”、“3”、“4”……

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

在获取用户名后便会不断地接受用户端发来的消息(即聊天内容),结束后关闭连接。

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

如果用户断开连接,将该用户从用户列表中删除,然后更新用户列表。

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

将地址与数据(需发送给客户端)存入messages队列。

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

服务端在接受到数据后,会对其进行一些处理然后发送给客户端,如下图,对于聊天内容,服务端直接发送给客户端,而对于用户列表,便由json.dumps处理后发送。

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

client.py
建立连接,发送用户名及判断是否为私聊消息,私聊用~识别

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

接受来自服务器发送的消息

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

对接收到的消息进行判断,如果是在线用户列表(用json.dumps处理过),便清空在线用户列表框,并将此列表输出在在线用户列表框中。

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

如果是聊天内容,便将其输出在聊天内容显示框中。

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

设置登录窗口

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

设置消息界面

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

设置在线用户列表。

Python实现网络聊天室的示例代码(支持多人聊天与私聊)

完整代码:
serve.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import socket
import threading
import queue
import json # json.dumps(some)打包  json.loads(some)解包
import os
import os.path
import sys
 
 
ip = '127.0.0.1'
port = 9999   # 端口
messages = queue.queue()
users = []  # 0:username 1:connection
lock = threading.lock()
 
def onlines():  # 统计当前在线人员
  online = []
  for i in range(len(users)):
    online.append(users[i][0])
  return online
 
class chatserver(threading.thread):
  global users, que, lock
 
  def __init__(self):     # 构造函数
    threading.thread.__init__(self)
    self.s = socket.socket(socket.af_inet, socket.sock_stream)
    os.chdir(sys.path[0])
# 接受来自客户端的用户名,如果用户名为空,使用用户的ip与端口作为用户名。如果用户名出现重复,则在出现的用户名依此加上后缀“2”、“3”、“4”……
  def receive(self, conn, addr):       # 接收消息
    user = conn.recv(1024)    # 用户名称
    user = user.decode()
    if user == '用户名不存在':
      user = addr[0] + ':' + str(addr[1])
    tag = 1
    temp = user
    for i in range(len(users)):   # 检验重名,则在重名用户后加数字
      if users[i][0] == user:
        tag = tag + 1
        user = temp + str(tag)
    users.append((user, conn))
    users = onlines()
    self.load(users,addr)
    # 在获取用户名后便会不断地接受用户端发来的消息(即聊天内容),结束后关闭连接。
    try:
      while true:
        message = conn.recv(1024)      # 发送消息
        message = message.decode()
        message = user + ':' + message
        self.load(message,addr)
      conn.close()
    # 如果用户断开连接,将该用户从用户列表中删除,然后更新用户列表。
    except
      j = 0      # 用户断开连接
      for man in users:
        if man[0] == user:
          users.pop(j)    # 服务器段删除退出的用户
          break
        j = j+1
 
      users = onlines()
      self.load(users,addr)
      conn.close()
 
# 将地址与数据(需发送给客户端)存入messages队列。
  def load(self, data, addr):
    lock.acquire()
    try:
      messages.put((addr, data))
    finally:
      lock.release()   
 
  # 服务端在接受到数据后,会对其进行一些处理然后发送给客户端,如下图,对于聊天内容,服务端直接发送给客户端,而对于用户列表,便由json.dumps处理后发送。
  def senddata(self): # 发送数据
    while true:
      if not messages.empty():
        message = messages.get()
        if isinstance(message[1], str):
          for i in range(len(users)):
            data = ' ' + message[1]
            users[i][1].send(data.encode())
            print(data)
            print('\n')
 
        if isinstance(message[1], list):
          data = json.dumps(message[1])
          for i in range(len(users)):
            try:
              users[i][1].send(data.encode())
            except:
              pass
 
  def run(self):
    self.s.bind((ip,port))
    self.s.listen(5)
    q = threading.thread(target=self.senddata)
    q.start()
    while true:
      conn, addr = self.s.accept()
      t = threading.thread(target=self.receive, args=(conn, addr))
      t.start()
    self.s.close()
if __name__ == '__main__':
  cserver = chatserver()
cserver.start()

client.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import socket
import tkinter
import tkinter.messagebox
import threading
import json
import tkinter.filedialog
from tkinter.scrolledtext import scrolledtext
 
ip = ''
port = ''
user = ''
listbox1 = '' # 用于显示在线用户的列表框
show = 1 # 用于判断是开还是关闭列表框
users = [] # 在线用户列表
chat = '------group chat-------' # 聊天对象
 
#登陆窗口
 
root0 = tkinter.tk()
root0.geometry("300x150")
root0.title('用户登陆窗口')
root0.resizable(0,0)
one = tkinter.label(root0,width=300,height=150,bg="lightblue")
one.pack()
 
ip0 = tkinter.stringvar()
ip0.set('')
user = tkinter.stringvar()
user.set('')
 
labelip = tkinter.label(root0,text='ip地址',bg="lightblue")
labelip.place(x=20,y=20,width=100,height=40)
entryip = tkinter.entry(root0, width=60, textvariable=ip0)
entryip.place(x=120,y=25,width=100,height=30)
 
labeluser = tkinter.label(root0,text='用户名',bg="lightblue")
labeluser.place(x=20,y=70,width=100,height=40)
entryuser = tkinter.entry(root0, width=60, textvariable=user)
entryuser.place(x=120,y=75,width=100,height=30)
 
def login(*args):
    global ip, port, user
    ip, port = entryip.get().split(':')
    user = entryuser.get()
    if not user:
        tkinter.messagebox.showwarning('warning', message='用户名为空!')
    else:
        root0.destroy()
 
loginbutton = tkinter.button(root0, text ="登录", command = login,bg="yellow")
loginbutton.place(x=135,y=110,width=40,height=25)
root0.bind('<return>', login)
 
root0.mainloop()
 
# 建立连接
s = socket.socket(socket.af_inet, socket.sock_stream)
s.connect((ip, int(port)))
if user:
  s.send(user.encode()) # 发送用户名
else:
  s.send('用户名不存在'.encode())
  user = ip + ':' + port
 
# 聊天窗口
root1 = tkinter.tk()
root1.geometry("640x480")
root1.title('群聊')
root1.resizable(0,0)
 
# 消息界面
listbox = scrolledtext(root1)
listbox.place(x=5, y=0, width=640, height=320)
listbox.tag_config('tag1', foreground='red',backgroun="yellow")
listbox.insert(tkinter.end, '欢迎进入群聊,大家开始聊天吧!', 'tag1')
 
input = tkinter.stringvar()
input.set('')
entryiuput = tkinter.entry(root1, width=120, textvariable=input)
entryiuput.place(x=5,y=320,width=580,height=170)
 
# 在线用户列表
listbox1 = tkinter.listbox(root1)
listbox1.place(x=510, y=0, width=130, height=320)
 
 
def send(*args):
    message = entryiuput.get() + '~' + user + '~' + chat
    s.send(message.encode())
    input.set('')
 
sendbutton = tkinter.button(root1, text ="\n发\n\n\n送",anchor = 'n',command = send,font=('helvetica', 18),bg = 'white')
sendbutton.place(x=585,y=320,width=55,height=300)
root1.bind('<return>', send)
 
 
def receive():
    global uses
    while true:
        data = s.recv(1024)
        data = data.decode()
        print(data)
        try:
            uses = json.loads(data)
            listbox1.delete(0, tkinter.end)
            listbox1.insert(tkinter.end, "当前在线用户")
            listbox1.insert(tkinter.end, "------group chat-------")
            for x in range(len(uses)):
                listbox1.insert(tkinter.end, uses[x])
            users.append('------group chat-------')
        except:
            data = data.split('~')
            message = data[0]
            username = data[1]
            chatwith = data[2]
            message = '\n' + message
            if chatwith == '------group chat-------'# 群聊
                if username == user:
                    listbox.insert(tkinter.end, message)
                else:
                    listbox.insert(tkinter.end, message)
            elif username == user or chatwith == user: # 私聊
                if username == user:
                    listbox.tag_config('tag2', foreground='red')
                    listbox.insert(tkinter.end, message, 'tag2')
                else:
                    listbox.tag_config('tag3', foreground='green')
                    listbox.insert(tkinter.end, message,'tag3')
 
            listbox.see(tkinter.end)
r = threading.thread(target=receive)
r.start() # 开始线程接收信息
 
root1.mainloop()
s.close()

到此这篇关于python实现网络聊天室的示例代码(支持多人聊天与私聊)的文章就介绍到这了,更多相关python 网络聊天室内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_43916997/article/details/110761676

相关文章

热门资讯

yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
2021年耽改剧名单 2021要播出的59部耽改剧列表
2021年耽改剧名单 2021要播出的59部耽改剧列表 2021-03-05
返回顶部