今天把上學期瞎折騰的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:
轉載請標明出處