Python網路程式設計(子程式的建立與處理、簡單群聊工具)
前言:
昨天我們已經瞭解了多程式的原理以及它的實際使用
Unix/Linux作業系統提供了一個
fork()
系統呼叫,它非常特殊。普通的函式呼叫,呼叫一次,返回一次,但是
fork()
呼叫一次,返回兩次,因為作業系統自動把當前程式(稱為父程式)複製了一份(稱為子程式),然後,分別在父程式和子程式內返回。子程式永遠返回
0
,而父程式返回子程式的ID。這樣做的理由是,一個父程式可以fork出很多子程式,所以,父程式要記下每個子程式的ID,而子程式只需要呼叫
getppid()
就可以拿到父程式的ID。Python的
os
模組封裝了常見的系統呼叫,其中就包括fork
,可以在Python程式中輕鬆建立子程式
既然是程式那麼就會有執行和退出
接下來我們就來了解一下程式的退出以及處理
孤兒程式:
當父程式優先於子程式退出,此時子程式就會成為孤兒程式
特徵:
孤兒程式會被系統指定程式收養,即系統程式會成為
這個孤兒程式新的父程式,系統程式會自動處理程式退出狀態
殭屍程式:
當子程式優先於父程式退出,父程式沒有處理子程式的退出狀態
此時子程式就會成為殭屍程式
殭屍程式會滯留部分PCB資訊在記憶體中,大量的殭屍程式會消耗系統給的記憶體資源,
所以要儘量避免殭屍程式的產生
如何避免殭屍程式的產生:
1.父程式先退出
2.父程式處理子程式狀態
PID,status = os.wait
功能:
在父程式中阻塞等待處理子程式的退出
返回值:
pid :退出的那個子程式的PID號
status :子程式的退出狀態
獲取原來的退出狀態:
wait(status)
pid,status = os.waitpid(pid,option)
功能:在父程式阻塞等待處理子程式的退出
引數 :
pid -1 表示等待任意子程式退出
>0 表示等待對應PID號的子程式退出
option
option
0 表示阻塞等待
WNOHANG 表示非阻塞
WNOHANG 表示非阻塞
返回值:pid
退出的那個子程式的PID號
status 子程式的退出狀態
status 子程式的退出狀態
建立二級子程式
- 父程式建立子程式等待程式退出
- 子程式建立下一個程式,然後立即退出
- 二級子程式成為孤兒程式 處理具體工作
multiprocessing 模組建立程式
1.需要將要做的事情封裝為函式2.使用multiprocessing提供的process 建立程式物件3.通過程式物件和process初始化程式進行程式的設定,繫結函式4.啟動程式,會自動執行繫結的函式5.完成程式的回收
建立程式物件:
process()
功能:
建立程式物件
引數:
target:函式物件
name 給程式新名稱()
args:元組 用來給target函式位置傳參
kwargs:字典 用來給target函式鍵值傳參
p.start()
功能:
啟動程式,自動執行terget繫結函式,
此時程式被建立
p.join([timeout])
功能:
等待阻塞子程式退出
引數:超時檢測
如果不使用join回收可能後產生殭屍程式
- 使用multiprocessing建立程式子程式同樣複製父程式的全部記憶體空間
- 之後有自己的獨立空間 執行上互不干擾 子程式也有自己的PID特有資源等
- 使用multiprocessing建立子程式,一般父程式功能就是建立子程式
- 回收子程式,返回事件交給子程式完成
簡單群聊:
功能:
類似QQ群聊
1.進入聊天室需要輸入姓名 姓名不能重複
2.有人進入聊天室會向其他人發起通知 xxx進入聊天室
3.如果一個人發訊息則其他人都能收到 xxx說:…
4.如果某個人退出聊天室也會收到通知 xxx退出聊天室
5.服務端可以喊話:此時群裡所有的都能收到服務端訊息 管理員說:…
伺服器端:
from socket import *
import os, sys
# 傳送管理員訊息
def do_child(s, addr):
while True:
msg = input("管理員訊息:")
msg = "C 管理員 " + msg
s.sendto(msg.encode(), addr)
# 使用者登入
def do_login(s, user, name, addr):
if (name in user) or name == "管理員":
s.sendto("該使用者已存在".encode(), addr)
return
s.sendto(b`OK`, addr)
# 通知所有人
msg = "
歡迎 %s 進入聊天室" % name
for i in user:
s.sendto(msg.encode(), user[i])
# 插入user
user[name] = addr
def do_chat(s, user, name, data):
msg = "
{} 說: {}".format(name, data)
for i in user:
if i != name:
s.sendto(msg.encode(), user[i])
def do_quit(s, user, name):
msg = "
%s 離開了聊天室" % 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):
# 用於儲存使用者 {`Alex`:(`127.0.0.1`,8888)}
user = {}
while True:
msg, addr = s.recvfrom(1024)
msgList = msg.decode().split(` `)
if msgList[0] == `L`:
do_login(s, user, msgList[1], addr)
elif msgList[0] == `C`:
# "C Levi [I miss you]"
data = ` `.join(msgList[2:])
do_chat(s, user, msgList[1], data)
elif msgList[0] == `Q`:
do_quit(s, user, msgList[1])
# 建立套接字,網路連線,建立父子程式
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()
客戶端:
from socket import *
import sys, os
def login(s, ADDR):
while True:
name = input("請輸入使用者名稱:")
msg = "L " + name
s.sendto(msg.encode(), ADDR)
# 接收登入結果
data, addr = s.recvfrom(1024)
if data.decode() == `OK`:
print("@進入聊天室@")
return name
else:
print(data.decode())
# 傳送訊息
def do_child(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 do_parent(s):
while True:
msg, addr = s.recvfrom(1024)
if msg.decode() == `EXIT`:
sys.exit(0)
print(msg.decode() + "
發言(quit退出):",end="")
# main控制套接字的建立
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)
name = login(s, ADDR)
if name:
pid = os.fork()
if pid < 0:
sys.exit("建立子程式失敗")
elif pid == 0:
do_child(s, name, ADDR)
else:
do_parent(s)
else:
return
if __name__ == "__main__":
main()
相關文章
- Python(簡單圖形和檔案處理)程式設計Python程式設計
- py網路工具程式設計程式設計
- 程式設計師程式設計時的簡單方法與技巧程式設計師
- 好程式設計師Python培訓分享Python程式設計中常見的異常處理程式設計師Python
- 程式設計實習MOOC/6908/C:簡單的學生資訊處理程式實現程式設計
- linux網路程式設計中的errno處理Linux程式設計
- python 網路篇(網路程式設計)Python程式設計
- 手把手教你用Python建立簡單的神經網路(附程式碼)Python神經網路
- 簡單理解非同步程式設計(python)和非同步程式設計(nodejs)非同步程式設計PythonNodeJS
- Socket網路程式設計基礎與實踐:建立高效的網路通訊程式設計
- 最簡單的C程式設計--順序程式設計C程式程式設計
- Python 程式設計高效技巧:最佳化、異常處理與效能提升Python程式設計
- Python網路程式設計——程式Python程式設計
- 好程式設計師Python培訓分享Python異常處理程式設計師Python
- 簡單是 Python 程式設計的第一要則Python程式設計
- python網路-Socket之TCP程式設計(26)PythonTCP程式設計
- Proteus實現簡單51程式的設計與模擬
- 程式設計師,你有新的訂單請及時處理!程式設計師
- Python通用程式設計 - 第五章:檔案處理Python程式設計
- MATLAB神經網路工具箱(程式碼簡單實現)Matlab神經網路
- 網際網路竟能如此簡單!風變程式設計改變了我對網際網路的認知程式設計
- 資料預處理速度高倍提升,3行python程式碼簡單搞定!Python
- 建立一個簡單的小程式
- (Python程式設計 | 系統程式設計 | 並行系統工具 | 程式退出)Python程式設計並行
- 風變程式設計,讓程式設計學習更簡單!程式設計
- 簡單的程式碼生成工具
- c++簡單程式設計-3C++程式設計
- 簡單介紹python程式設計之檔案讀寫Python程式設計
- 程式設計師自黑的梗!產品經理:功能實現起來很簡單!—程式設計師:*&%程式設計師
- 網路通訊程式設計程式設計
- linuxshell程式設計實戰-編寫簡單的指令碼實用工具Linux程式設計指令碼
- 最好的程式是程式設計師在處理其他事情時編寫的程式!程式設計師
- 01 Python3程式設計之程式設計語法簡介Python程式設計
- Python Selenium的簡單演示程式Python
- python:socket網路程式設計Python程式設計
- Python程式設計:Counter計數器-dict字典的子類Python程式設計
- 精研3道簡單的網易2018校招程式設計題程式設計
- 二、GO 程式設計模式:錯誤處理Go程式設計設計模式