1. 程式人生 > >自己寫的聊天室專案

自己寫的聊天室專案

作業:(服務端,客戶端)
寫一個聊天室
功能:類似qq群聊
1.進入聊天室需要輸入姓名,提示一下姓名不能重複

2.有人進入聊天室會向其他人傳送通知
xxx 進入了聊天室
3.一個人發訊息,其他人會收到訊息,自己不收到
xxx 說:xxxxxxxxxxx
4.某人退出聊天室,其他人也會收到通知
xxx 退出了聊天室
5.管理員喊話功能(從服務端傳送訊息,所有客戶端都能接收到)
管理員說:xxxxxx

功能模型:轉發
需要的技術:套接字通訊 udp套接字
使用者儲存:字典或列表
訊息收發的隨意性:多程序(fork)

程式碼設計:
1.封裝 將每個功能封裝為函式
2.介面測試(每實現一步測試一步)

程式碼的編寫流程
1.搭建網路連線
2.建立多程序
3.每個程序功能編寫
4.專案功能模組實現

進入聊天室???????
客戶端:輸入姓名,將資訊發給服務端(L name)標誌位
等待服務端回覆 根據回覆判斷是否登入成功

服務端:接受請求資訊 判斷請求型別 判斷使用者名稱是否存在
如果存在回覆不能登入,如果不 存在回覆可以登入並插入到資料結構
傳送通知給其他使用者

def fun(l):
l.append(6)
#傳遞可變型別引數到函式中,列印原來的形參,同樣改變了
#對可變型別的修改會影響到原來的實參
#傳遞一個不可變型別引數,對引數的修改不會影響原引數
l=[1,2,3,4,5]
fun(l)
print(l)

def fun(l):
l=‘world’
#傳遞不可變型別引數到函式中,列印原來的形參,沒有改變
l=“hello”
fun(l)

print(l)

聊天
客戶端:建立父子程序 傳送聊天請求/接收聊天資訊
服務端:接收請求資訊 將訊息轉發給其他客戶端

退出

管理員訊息

程式碼:服務端
#!/usr/bin/env python3
#coding=utf-8

#文件說明,作者,聯絡方式,
‘’’
name=Yxp
email:[email protected]
date:2018-9
class:AID
introduce:Chatroom server
env:python3.5
‘’’
from socket import *
import os, sys

def do_login(s,user,name,addr):
if (name in user) or name==‘管理員’:
s.sendto(‘該使用者已存在’.encode(),addr)
return
s.sendto(b’OK’,addr)

#通知其他人
msg='\n歡迎%s進入聊天室'%name
for i in user:
    s.sendto(msg.encode(),user[i])
#插入使用者,user是可變型別,因此可以直接修改
user[name]=addr

def do_chat(s,user,name,text):
msg ="\n%s說:%s"%(name,text)
for i in user:
if i!=name:
s.sendto(msg.encode(),user[i])

#退出聊天室
def do_quit(s,user,name):
msg=’\n’+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):
#儲存結構{‘zhangssan’?‘127.0.0.1’,9999)}
user={}

while True:
    msg,addr = s.recvfrom(1024)
    msgList = msg.decode().split(' ')

    #區分請求型別
    if msgList[0]=='L':
        fanhui=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’,8888)

#建立套接字
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()
客戶端
#client.py
from socket import *
import sys,os

#傳送訊息
def send_msg(s,name,addr):
while True:
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)

#接收訊息
def recv_msg(s):
while True:
data,addr=s.recvfrom(2048)
if data.decode()==‘EXIT’:
sys.exit(0)

    print(data.decode()+"\n發言:",end='')

#建立套接字,然後登入,建立子程序
def main():
if len(sys.argv)❤️:
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
    #傳送登入請求
    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()