多線程原理:TCP服務(wù)器會(huì)創(chuàng)建一個(gè)線程池,每當(dāng)有客戶端請(qǐng)求連接的時(shí)候,它便會(huì)從線程池中分配一個(gè)線程同客戶端建立連接,當(dāng)客戶端中斷連接后,線程便銷毀。
SocketServer 是標(biāo)準(zhǔn)庫(kù)中一個(gè)高級(jí)別的模塊。用于簡(jiǎn)化網(wǎng)絡(luò)客戶與服務(wù)器的實(shí)現(xiàn)。
socketserver模塊中分兩大類:server類(解決連接問題)和request類(解決通信問題)
我們將服務(wù)器做為中轉(zhuǎn)站來處理信息,一方面與客戶端互動(dòng),另一方面進(jìn)行消息轉(zhuǎn)發(fā)。
大體思路確定下來后,需要確定一些通信規(guī)則:
1. 客戶端與服務(wù)器建立連接后,需要輸入用戶名登入,若用戶名已存在,將reuse反饋給用戶,用戶輸出錯(cuò)誤信息,退出
2. 用戶輸入正確的用戶名后,即可進(jìn)行通信了。如果未選擇通信對(duì)象,則服務(wù)器會(huì)反饋信息,提示用戶選擇通信對(duì)象
3. 選擇通信對(duì)象的方法為,輸入to:username,如果所選擇的對(duì)象不存在,反饋錯(cuò)誤信息,重新輸入
4.當(dāng)正確選擇通信對(duì)象后,雙方建立連接,通過服務(wù)器中轉(zhuǎn)信息進(jìn)行通信
5.在通信中,若發(fā)送‘quit',則結(jié)束發(fā)送消息的線程,并指示服務(wù)器該用戶準(zhǔn)備登出,服務(wù)器刪除該用戶后,反饋消息給用戶,用戶結(jié)束接收消息的線程并退出
6.如果A正在與C通信,此時(shí)B向A發(fā)送信息,則A的通信窗口變?yōu)榕cB的通信窗口,即接收到B消息后,A發(fā)出的消息不再是給C,而是默認(rèn)給B
實(shí)現(xiàn)代碼:
#!/usr/bin/python
'test TCP server'
from socket import *
from time import ctime
import threading #多線程模塊
import re #正則表達(dá)式模塊
HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)
def Deal(sock, user):
while True:
data = sock.recv(BUFSIZ) #接收用戶的數(shù)據(jù)
if data == 'quit': #用戶退出
del clients[user]
sock.send(data)
sock.close()
print '%s logout' %user
break
elif re.match('to:.+', data) is not None: #選擇通信對(duì)象
data = data[3:]
if clients.has_key(data):
chatwith[sock] = clients[data]
chatwith[clients[data]] = sock
else:
sock.send('the user %s is not exist' %data)
else:
if chatwith.has_key(sock): #進(jìn)行通信
chatwith[sock].send("[%s] %s: %s" %(ctime(), user, data))
else:
sock.send('Please input the user who you want to chat with')
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
clients = {} #提供 用戶名->socket 映射
chatwith = {} #提供通信雙方映射
while True:
print 'waiting for connection...'
tcpCliSock, addr = tcpSerSock.accept()
print '...connected from:',addr
username = tcpCliSock.recv(BUFSIZ) #接收用戶名
print 'The username is:',username
if clients.has_key(username): #查找用戶名
tcpCliSock.send("Reuse") #用戶名已存在
tcpCliSock.close()
else: 無錫婦科醫(yī)院排行 http://www.0510bhyy.com/
tcpCliSock.send("Welcome!") #登入成功
clients[username] = tcpCliSock
chat = threading.Thread(target = Deal, args = (tcpCliSock,username)) #創(chuàng)建新線程進(jìn)行處理
chat.start() #啟動(dòng)線程
tcpSerSock.close()
#!/usr/bin/python
'test tcp client'
from socket import *
import threading
HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)
threads = []
def Send(sock, test): #發(fā)送消息
while True:
data = raw_input('>')
tcpCliSock.send(data)
if data == 'quit':
break
def Recv(sock, test): #接收消息
while True:
data = tcpCliSock.recv(BUFSIZ)
if data == 'quit':
sock.close() #退出時(shí)關(guān)閉socket
break
print data
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
print 'Please input your username:',
username = raw_input()
tcpCliSock.send(username)
data = tcpCliSock.recv(BUFSIZ)
if data == 'Reuse':
print 'The username has been used!'
else:
print 'Welcome!'
chat = threading.Thread(target = Send, args = (tcpCliSock,None)) #創(chuàng)建發(fā)送信息線程
threads.append(chat)
chat = threading.Thread(target = Recv, args = (tcpCliSock,None)) #創(chuàng)建接收信息線程
threads.append(chat)
for i in range(len(threads)): #啟動(dòng)線程
threads[i].start()
threads[0].join() #在我們的設(shè)計(jì)中,send線程必然先于recv線程結(jié)束,所以此處只需要調(diào)用send的join,等待recv線程的結(jié)束。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
