pythonで書いた簡易チャットルームで、マルチスレッド、udpソケットを使います.
4627 ワード
チャットルームを書く
机能:qq群聊1.チャットルームに入るには名前を入力クライアントがサービス側に送り、サービス側がクライアント2に送る必要がある.誰かがチャットルームに入ると他の人に通知***を送ってチャットルームに入る.一人でメッセージを送ると、他の人はメッセージを受け取ります.ある人がチャットルームを脱退すると、他の人も***を受け取ってチャットルームを脱退した.管理者が叫ぶ:サービス側はメッセージを送信して、すべてのクライアントはすべて管理者を受け取ることができます:*****
機能モデル:転送に必要な技術:ソケット通信udpソケット
≪ユーザー・ストレージ|User Storage|emdw≫:ディクショナリまたはリスト・メッセージの送受信の随意性
コード設計1.カプセル化:各機能を関数2にカプセル化する.インタフェーステスト(実装ごとに1ステップテスト)
コード作成プロセス
ネットワーク接続の構築-->マルチプロセスの作成-->各プロセス機能の作成-->プロジェクト機能モジュールの実装
チャットルームに入る
クライアント:名前を入力してサービス側(L name)にメッセージを送るサービス側の返信待ち返信返信返信返信よりログイン成功したか否かを判定サービス側:リクエスト情報を受け付けて要求タイプを判定ユーザ名が存在しない場合ログイン可能か否かを判定し、データ構造に挿入して他のユーザに通知する
チャットクライアント:親子プロセスの作成チャットリクエストの送信/チャット情報の受信
サービス側:要求情報を受け入れ、メッセージを他のクライアントに転送する
クライアント
サービス側
机能:qq群聊1.チャットルームに入るには名前を入力クライアントがサービス側に送り、サービス側がクライアント2に送る必要がある.誰かがチャットルームに入ると他の人に通知***を送ってチャットルームに入る.一人でメッセージを送ると、他の人はメッセージを受け取ります.ある人がチャットルームを脱退すると、他の人も***を受け取ってチャットルームを脱退した.管理者が叫ぶ:サービス側はメッセージを送信して、すべてのクライアントはすべて管理者を受け取ることができます:*****
機能モデル:転送に必要な技術:ソケット通信udpソケット
≪ユーザー・ストレージ|User Storage|emdw≫:ディクショナリまたはリスト・メッセージの送受信の随意性
コード設計1.カプセル化:各機能を関数2にカプセル化する.インタフェーステスト(実装ごとに1ステップテスト)
コード作成プロセス
ネットワーク接続の構築-->マルチプロセスの作成-->各プロセス機能の作成-->プロジェクト機能モジュールの実装
チャットルームに入る
クライアント:名前を入力してサービス側(L name)にメッセージを送るサービス側の返信待ち返信返信返信返信よりログイン成功したか否かを判定サービス側:リクエスト情報を受け付けて要求タイプを判定ユーザ名が存在しない場合ログイン可能か否かを判定し、データ構造に挿入して他のユーザに通知する
チャットクライアント:親子プロセスの作成チャットリクエストの送信/チャット情報の受信
サービス側:要求情報を受け入れ、メッセージを他のクライアントに転送する
クライアント
# client.py
from socket import *
import sys
import os
#
def recv_msg(s):
while True:
data, addr = s.recvfrom(2048)
if data.decode() == 'EXIT':
sys.exit(0)
print(data.decode() + ' :', end = "")
#
def send_msg(s, name, ADDR):
while True:
try:
text = input(">>")
# quit
if text.strip() == "quit":
msg = "Q " + name
s.sendto(msg.encode(), ADDR)
sys.exit(" ")
msg = 'C %s %s' % (name, text)
s.sendto(msg.encode(), ADDR)
except KeyboardInterrupt:
msg = "Q " + name
s.sendto(msg.encode(), ADDR)
sys.exit(" ")
# , ,
def main():
if len(sys.argv) < 3:
print('argv is error')
return
HOST = sys.argv[1]
PORT = int(sys.argv[2])
ADDR = (HOST, PORT)
#
s = socket(AF_INET, SOCK_DGRAM)
while True:
name = input(' :')
msg = 'L ' + name
# print('11111')
#
s.sendto(msg.encode(), ADDR)
#
data, addr = s.recvfrom(1024)
if data.decode() == 'OK':
print(' ')
break
else:
#
print(data.decode())
#
pid = os.fork()
if pid < 0:
sys.exit(' ')
elif pid == 0:
send_msg(s, name, ADDR)
else:
recv_msg(s)
if __name__ == '__main__':
main()
サービス側
#!/usr/bin/env python3
# coding = utf-8
'''
name:zsj
email:[email protected]
date:2018-9
introduce:Chatroom server
env: python3.5
'''
from socket import *
import os
import sys
#
def do_login(s, user, name, addr):
if (name in user) or name == ' ':
s.sendto(' '.encode(), addr)
return
else:
s.sendto('OK'.encode(), addr)
#
msg = '
%s ' % name
for i in user:
s.sendto(msg.encode(), user[i])
#
user[name] = addr
def do_chat(s, user, name, text):
msg = '
%s %s
' % (name, text)
for i in user:
if i != name:
s.sendto(msg.encode(), user[i])
#
def do_quit(s, user, name):
msg = name + ' '
for i in user:
if i == name:
s.sendto(b'EXIT', user[i])
else:
s.sendto(msg.encode(), user[i])
del user[name]
#
def do_parent(s):
# ({'zhangsan':(127.0.0.1,9999)})
user = {}
while True:
msg, addr = s.recvfrom(1024)
msgList = msg.decode().split(' ')
#
if msgList[0] == 'L': # L
do_login(s, user, msgList[1], addr)
elif msgList[0] == 'C':
do_chat(s, user, msgList[1], ' '.join(msgList[2:]))
elif msgList[0] == 'Q':
do_quit(s, user, msgList[1])
#
def do_child(s, addr):
while True:
msg = input(' :')
msg = 'C ' + msg
s.sendto(msg.encode(), addr)
# , ,
def main():
# server address
ADDR = ('0.0.0.0', 9999)
#
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(ADDR)
#
pid = os.fork()
if pid < 0:
sys.exit(' ')
elif pid == 0:
do_child(s, ADDR)
else:
do_parent(s)
if __name__== "__main__":
main()