溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Python網(wǎng)絡(luò)編程基于多線程實(shí)現(xiàn)多用戶(hù)全雙工聊天功能

發(fā)布時(shí)間:2020-08-02 19:46:23 來(lái)源:網(wǎng)絡(luò) 閱讀:259 作者:nineteens 欄目:編程語(yǔ)言

  多線程原理:TCP服務(wù)器會(huì)創(chuàng)建一個(gè)線程池,每當(dāng)有客戶(hù)端請(qǐng)求連接的時(shí)候,它便會(huì)從線程池中分配一個(gè)線程同客戶(hù)端建立連接,當(dāng)客戶(hù)端中斷連接后,線程便銷(xiāo)毀。

  SocketServer 是標(biāo)準(zhǔn)庫(kù)中一個(gè)高級(jí)別的模塊。用于簡(jiǎn)化網(wǎng)絡(luò)客戶(hù)與服務(wù)器的實(shí)現(xiàn)。

  socketserver模塊中分兩大類(lèi):server類(lèi)(解決連接問(wèn)題)和request類(lèi)(解決通信問(wèn)題)

  我們將服務(wù)器做為中轉(zhuǎn)站來(lái)處理信息,一方面與客戶(hù)端互動(dòng),另一方面進(jìn)行消息轉(zhuǎn)發(fā)。

  大體思路確定下來(lái)后,需要確定一些通信規(guī)則:

  1. 客戶(hù)端與服務(wù)器建立連接后,需要輸入用戶(hù)名登入,若用戶(hù)名已存在,將reuse反饋給用戶(hù),用戶(hù)輸出錯(cuò)誤信息,退出

  2. 用戶(hù)輸入正確的用戶(hù)名后,即可進(jìn)行通信了。如果未選擇通信對(duì)象,則服務(wù)器會(huì)反饋信息,提示用戶(hù)選擇通信對(duì)象

  3. 選擇通信對(duì)象的方法為,輸入to:username,如果所選擇的對(duì)象不存在,反饋錯(cuò)誤信息,重新輸入

  4.當(dāng)正確選擇通信對(duì)象后,雙方建立連接,通過(guò)服務(wù)器中轉(zhuǎn)信息進(jìn)行通信

  5.在通信中,若發(fā)送‘quit',則結(jié)束發(fā)送消息的線程,并指示服務(wù)器該用戶(hù)準(zhǔn)備登出,服務(wù)器刪除該用戶(hù)后,反饋消息給用戶(hù),用戶(hù)結(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) #接收用戶(hù)的數(shù)據(jù)

  if data == 'quit': #用戶(hù)退出

  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 = {} #提供 用戶(hù)名->socket 映射

  chatwith = {} #提供通信雙方映射

  while True:

  print 'waiting for connection...'

  tcpCliSock, addr = tcpSerSock.accept()

  print '...connected from:',addr

  username = tcpCliSock.recv(BUFSIZ) #接收用戶(hù)名

  print 'The username is:',username

  if clients.has_key(username): #查找用戶(hù)名

  tcpCliSock.send("Reuse") #用戶(hù)名已存在

  tcpCliSock.close()

  else:無(wú)錫婦科醫(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é)束。


向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI