チャットルーム
需要分析:製品(クライアント)のVisioのプロトタイプを確立します
必要に応じて、実現する機能を計画します
テクニカル分析:機能に応じて実装技術を決定します
ネットワーク通信:udpネットワークテクノロジー
消息收发模型
* 转发 客户端--> 服务端-->其他客户端
* 用户进入聊天室时要存储用户地址 怎么存
{
name:address}
[(name,address),....]
class Person:
def __init__(self,name,address):
self.name = name
self.address = address
* 收发消息互相不干扰
父进程 发送消息
子进程 接收消息
- 機能モジュール分析(パッケージ):分解
1つの機能を実現する1つの機能をテストする
- 関数ラッパー
チャットルーム入力し
たチャット
チャットルームを終了します
通信プロトコルの設計
请求类型 数据
进入 L name
聊天 C name content
退出 E name
- サブモジュール固有のロジック設計
基本的なネットワーク構造を構築します
。サーバー:1。udpネットワーク通信を作成します
。2。クライアントメッセージを周期的に受信する準備をします。3
。要求に応じて適切な関数処理を呼び出します。
客户端: 1.创建udp套接字
チャットルームに入る
クライアント:1。名前を入力します
2.リクエストを送信し
ます3.サーバーからの通知結果を受け入れます
4. Y次にNを入力し、名前を再入力します
服务端: 1. 接收请求
- ユーザーが存在するかどうかを確認します
。3。Yはクライアントに入力できないことを
通知します。4。Nはクライアントにチャットルームに入るように通知します。
他のユーザーに
ユーザー情報を保存するよう通知します。
チャットする
クライアント:1。子プロセスを作成します
2.子プロセスはメッセージを周期的に受信します
3.親プロセスはメッセージを周期的に入力して送信します
服务端: 1. 接收消息
2. 将消息转发给其他人
チャットルームを出て、出口に入り、サインアウトします
クライアント:1。終了は終了を意味します
2.メッセージを送信します
3.プロセスを終了しますサーバー:1。メッセージを受信します
2.他のユーザーに通知します
3.ユーザーを削除します
- 最適化
関数:qqグループ関数に似ています
[1]チャットルームに入るには誰かが名前を入力する必要があります。名前を繰り返すことはできません
[2]誰かがチャットルームに入ると、他の人は通知を受け取ります:xxxがチャットルームに入りました
[3] 1人がメッセージを送信すると、他の人は次のメッセージを受信します:xxx:xxxxxxxxxxx
[4]誰かがチャットルームを離れると、他の人にも通知が届きます:xxxがチャットルームを離れました
[5]拡張機能:サーバーはすべてのユーザーにアナウンスを送信できます:管理者メッセージ:xxxxxxxxx
"""
author: xx
email: [email protected]
time: 2020-8-10
env: Python 3.6
socket and Process
"""
from socket import *
from multiprocessing import Process
サーバ
# 服务器地址
HOST = "0.0.0.0"
PORT = 8000
ADDR = (HOST, PORT)
# 存储结构用于存储用户信息 {name:address }
user = {
}
# 处理进入聊天室
def login(sock, name, addr):
# 如果用户存在
if name in user or "管理" in name:
sock.sendto(b"FAIL", addr)
return
# 告知用户进入
sock.sendto(b"OK", addr)
# 告知其他用户
msg = "欢迎 %s 进入聊天室" % name
for i in user:
sock.sendto(msg.encode(), user[i])
# 增加用户
user[name] = addr
# print("测试:",user)
# 聊天
def chat(sock, name, content):
msg = "%s : %s" % (name, content)
# 循环发送
for i in user:
if i == name:
continue
sock.sendto(msg.encode(), user[i])
# 退出
def exit(sock, name):
del user[name] # 删除用户
msg = "%s 退出了聊天室" % name
# 循环发送
for i in user:
sock.sendto(msg.encode(), user[i])
# 子进程处理请求
def request(sock):
# 循环接受客户端消息
while True:
# 所有请求都在这接受
data, addr = sock.recvfrom(1024 * 10)
# 对data做基本的解析
tmp = data.decode().split(' ', 2)
# 根据请求选择函数处理
if tmp[0] == "L":
# tmp --> ['L','name']
login(sock, tmp[1], addr)
elif tmp[0] == "C":
# tmp --> [C,name,content]
chat(sock, tmp[1], tmp[2])
elif tmp[0] == "E":
# tmp --> [E,name]
exit(sock, tmp[1])
# 启动函数用于搭建网络
def main():
# UDP套接字
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(ADDR)
# 创建子进程
p = Process(target=request, args=(sock,))
p.daemon = True
p.start()
while True:
content = input("管理员消息:")
# 服务端退出
if content == "exit":
break
msg = "C 管理员消息 "+content
# 从父进程发送给子进程
sock.sendto(msg.encode(),ADDR)
if __name__ == '__main__':
main()
クライアント
"""
chat room 客户端
发送请求 接收消息
"""
from socket import *
from multiprocessing import Process
import sys
# 服务器地址
ADDR = ("124.70.148.168", 8000)
# 进入聊天室
def login(sock):
while True:
name = input("Name:")
# 给服务端发请求
msg = "L " + name # 根据协议组织消息
sock.sendto(msg.encode(), ADDR)
# 等待结果
result, addr = sock.recvfrom(128)
# 约定OK作为请求成功的标志
if result.decode() == 'OK':
print("进入聊天室")
return name # 以name登录
else:
print("该用户已存在")
# 接收消息
def recv_msg(sock):
while True:
data, addr = sock.recvfrom(1024 * 10)
# 美化打印内容
msg = "\n" + data.decode() + "\n发言:"
print(msg, end="")
# 发送消息
def send_msg(sock, name):
while True:
try:
content = input("发言:")
except KeyboardInterrupt:
content = "exit"
# 输入exit要退出
if content == 'exit':
msg = "E " + name
sock.sendto(msg.encode(), ADDR)
sys.exit("退出聊天室")
msg = "C %s %s" % (name, content)
sock.sendto(msg.encode(), ADDR)
def main():
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(('0.0.0.0',55667))
# sock.sendto("测试信息".encode(),ADDR)
# 进入聊天室
name = login(sock)
# 创建子进程
p = Process(target=recv_msg, args=(sock,))
p.daemon = True # 子进程随父进程退出
p.start()
send_msg(sock, name) # 父进程发送消息
if __name__ == '__main__':
main()
実行では、最初にサーバーを実行し、次にクライアントを実行する必要があります