Python3 多線程下實現C/S交互模型

今天把上學期瞎折騰的TCP C/S交互模型重寫了一下,上學期是參考《Python核心編程》教程中的示例改寫的,但過於簡單,中心機能同時連接多臺節點機,但無法交互,作爲改進,便用多線程實現交互過程(C端啓動2個線程,一個用於接收,另一個用於發送)。歡迎大家改進!

TCPserver.py

# coding=utf-8
'''Author:Frank.ZhangLongqi
   Date:2017-3-18
   Environment:Win8,Python3.6
   E-mail:[email protected]
   Description:這是主程序,用於啓動線程監聽客戶端的連接,並與客戶端通信,可以同時和多個客戶端通信;
   Improvement:可以加入守護線程
'''
from socket import *
from time import ctime
import re,time
from atexit import register
from threading import Thread,Lock,BoundedSemaphore
import threading

HOST=' '
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)
lock = Lock()
MAX = 3#設置同時連接3個C端
pool = BoundedSemaphore(MAX)
n=3

tcpSerSock = socket(AF_INET,SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)

def connect():
    global n
    lock.acquire()
    pool.acquire()
    tcpCliSock,addr = tcpSerSock.accept()
    lock.release()
    print('...connected from:',addr)

    while True:
        data = tcpCliSock.recv(BUFSIZ).decode()
        if not data:
            #print(str(addr[0])+':'+str(addr[1])+": \"Goodbye\"")
            print(str(threading.currentThread().getName())+": \"Goodbye\"")
            print("There are remaining the number of threads is:",len(threading.enumerate())-2)
            break
        print(str(threading.currentThread().getName())+": \""+data+"\"")
        time.sleep(0.5)
        while True:
            data_to=input("to"+str(threading.currentThread().getName())+">")
            if data_to.strip()=="rcv":#輸入"rcv"相當於退出輸入狀態,而轉向接收狀態
                break
            data_to='['+ctime()+'] '+data_to
            tcpCliSock.send(data_to.encode())
            time.sleep(2)
    lock.acquire()
    pool.release()
    lock.release()
    tcpCliSock.close()
    
    #tcpSerSock.close()
def main():
    print("start at:",ctime())
    print('waiting for connection...')
    L=[]
    global n
    for i in range(n):
        t=Thread(target=connect,args=())
        L.append(t)
    for i in L:
        i.start()
    for i in L:
        i.join()
@register
def _atexit():
     print('all DONE at:',ctime())
if __name__ == '__main__':
    main()


TCPclient.py

#   coding=utf-8
'''每個C端都有1個接收線程和1個發送線程'''
from socket import *
import threading
import time
HOST = '127.0.0.1'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT)

tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)
def send():
    while True:
        data = input('>')
        if data.strip()=="exit":
            break
        tcpCliSock.send(data.encode())
        time.sleep(2)
    tcpCliSock.close()
def recv():
    while True:
        data_recv = tcpCliSock.recv(BUFSIZ).decode() 
        print(data_recv)
        time.sleep(5)

if __name__=="__main__":
    s=threading.Thread(target=send,args=())#發送線程
    r=threading.Thread(target=recv,args=())#接收線程
    s.start()
    r.start()
    s.join()
    r.join()

Demon:一個S端,3個C端

S(erver):Thread-1表示線程1發來的消息,toThread-1表示發給線程1的消息(鍵盤輸入),空回車可以實現回覆的對象在Thread-1~3間切換


C1:輸入exit表示退出連接,有時間戳打頭的行是收到的消息,沒有則是鍵盤輸入要發送的Message


C2:


C3:


轉載請標明出處

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章