自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何用Python實(shí)現(xiàn)TCP的連接與通信?

網(wǎng)絡(luò) 通信技術(shù)
網(wǎng)絡(luò)連接與通信是我們學(xué)習(xí)任何編程語(yǔ)言都繞不過(guò)的知識(shí)點(diǎn)。Python 也不例外,下面就介紹因特網(wǎng)的核心協(xié)議 TCP ,以及如何用 Python 實(shí)現(xiàn) TCP 的連接與通信。

 網(wǎng)絡(luò)連接與通信是我們學(xué)習(xí)任何編程語(yǔ)言都繞不過(guò)的知識(shí)點(diǎn)。Python 也不例外,下面就介紹因特網(wǎng)的核心協(xié)議 TCP ,以及如何用 Python 實(shí)現(xiàn) TCP 的連接與通信。

[[286840]]

TCP 協(xié)議

TCP協(xié)議(Transmission Control Protocol, 傳輸控制協(xié)議)是一種面向連接的傳輸層通信協(xié)議,它能提供高可靠性通信,像 HTTP/HTTPS 等網(wǎng)絡(luò)服務(wù)都采用 TCP 協(xié)議通訊。那么網(wǎng)絡(luò)通訊方面都會(huì)涉及到 socket 編程,當(dāng)然也包括 TCP 協(xié)議。

Network Socket

我們來(lái)看看定義:

Network Socket(網(wǎng)絡(luò)套接字)是計(jì)算機(jī)網(wǎng)絡(luò)中進(jìn)程間通信的數(shù)據(jù)流端點(diǎn),廣義上也代表操作系統(tǒng)提供的一種進(jìn)程間通信機(jī)制。

這些計(jì)算機(jī)術(shù)語(yǔ)都很學(xué)術(shù),難于理解,每個(gè)字都認(rèn)識(shí),加在一起就不認(rèn)識(shí)了。我們可以通俗地理解成發(fā)快遞:A 需要給 B 寄快遞,首先需要知道 B 的地址和手機(jī)號(hào)碼,那么這個(gè)地址就相當(dāng)于 網(wǎng)絡(luò)中的主機(jī) IP 地址,而手機(jī)就相當(dāng)于 主機(jī)的端口號(hào)。然后 A 還需要指定哪家快遞公司,是順豐還是中通?這個(gè)快遞公司就相當(dāng)于通信的傳輸協(xié)議。

TCP 連接流程

上述快遞的例子中,寄快遞的我們可以叫做客戶(hù)端,收快遞的我們叫做服務(wù)器。專(zhuān)業(yè)點(diǎn)就是主動(dòng)發(fā)起連接的一方叫做客戶(hù)端,被動(dòng)響應(yīng)的一方叫做服務(wù)器。例如,我們?cè)跒g覽器中訪問(wèn)百度搜索時(shí),我們自己的電腦就是客戶(hù)端,瀏覽器會(huì)向百度的服務(wù)器發(fā)送連接請(qǐng)求,如果百度的服務(wù)器接受了我們的請(qǐng)求,那么一個(gè) TCP 連接就建立起來(lái)了,后面就是百度向我們傳輸搜索結(jié)果了。

我們來(lái)看一個(gè)流程圖:

 

如何用 Python 實(shí)現(xiàn) TCP 的連接與通信?

 

TCP服務(wù)器的建立可以歸納這幾步:

  • 創(chuàng)建 socket(套接字)
  • 綁定 socket 的 IP 地址和端口號(hào)
  • 監(jiān)聽(tīng)客戶(hù)端的連接請(qǐng)求
  • 接受客戶(hù)端的連接請(qǐng)求
  • 與客戶(hù)端對(duì)話
  • 關(guān)閉連接

TCP客戶(hù)端的創(chuàng)建可總結(jié)為這幾步:

  • 創(chuàng)建 socket(套接字)
  • 連接服務(wù)器 socket
  • 與服務(wù)器對(duì)話
  • 關(guān)閉連接

這里需要注意的是 TCP 客戶(hù)端連接到服務(wù)器的 IP 和端口號(hào)必須是 TCP 服務(wù)器的 IP 和監(jiān)聽(tīng)的端口號(hào),服務(wù)器調(diào)用 listen() 開(kāi)始監(jiān)聽(tīng)端口,然后調(diào)用 accept() 時(shí)刻準(zhǔn)備接受客戶(hù)端的連接請(qǐng)求,此時(shí)服務(wù)器處于阻塞狀態(tài),直到服務(wù)器監(jiān)聽(tīng)到客戶(hù)端的請(qǐng)求后,接收請(qǐng)求并建立連接為止。

TCP 客戶(hù)端

創(chuàng)建 socket 連接,可以這樣做:

  1. # 導(dǎo)入socket庫(kù)import socket# 創(chuàng)建一個(gè)sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 建立連接s.connect(("127.0.0.1", 6000)) 

創(chuàng)建 socket 時(shí),第一個(gè)參數(shù) socket.AF_INET 表示指定使用 IPv4 協(xié)議,如果要使用 IPv6 協(xié)議,就指定為 socket.AF_INET6。SOCK_STREAM 指定使用面向流的 TCP 協(xié)議。然后我們調(diào)用 connect() 方法,傳入 IP 地址(或者域名),指定端口號(hào)就可以建立連接了。

接下來(lái)我們就可以向服務(wù)器發(fā)送數(shù)據(jù)了:

  1. s.send(b'Hello, Mr Right!'

接收數(shù)據(jù)時(shí),調(diào)用 recv(max) 方法,一次最多接收指定的字節(jié)數(shù),因此,在一個(gè) while 循環(huán)中反復(fù)接收,直到 recv() 返回空數(shù)據(jù),表示接收完畢,退出循環(huán)。

  1. #接收數(shù)據(jù) buffer=[] whileTrue: #每次最多接收1k字節(jié) d=s.recv(1024) ifd: buffer.append(d) else:break data=b''.join(buffer) 

最后,我們需要關(guān)閉連接,很簡(jiǎn)單:

  1. s.close() 

TCP 服務(wù)器

相比于客戶(hù)端,服務(wù)器端稍微復(fù)雜一些,需要先綁定一個(gè) IP 地址和端口號(hào),然后監(jiān)聽(tīng)客戶(hù)端的請(qǐng)求,收到請(qǐng)求后丟到一個(gè)線程去處理。

創(chuàng)建 socket 跟客戶(hù)端方法一樣:

  1. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

接下來(lái)需要綁定監(jiān)聽(tīng)地址和端口:

  1. s.bind(('127.0.0.1', 6000)) 

然后就可以開(kāi)始監(jiān)聽(tīng)端口了,監(jiān)聽(tīng)時(shí)需要傳入一個(gè)參數(shù),指定等待連接的最大數(shù)量:

  1. s.listen(5) 

接下來(lái)就是無(wú)限循環(huán)等待客戶(hù)端的連接,直到有連接請(qǐng)求過(guò)來(lái),就用一個(gè)線程去處理:

  1. whileTrue: #接受一個(gè)新連接 sock,addr=s.accept() #創(chuàng)建新線程來(lái)處理TCP連接 t=threading.Thread(target=tcplink,args=(sock,addr)) t.start() 

這里為什么需要多線程處理呢?想象一下菜鳥(niǎo)驛站,如果里面只有一個(gè)人的話,那么多個(gè)人寄件就需要排隊(duì),一個(gè)個(gè)來(lái);但是如果有多個(gè)人的話,那么每個(gè)人都可以處理一個(gè)寄件請(qǐng)求。

我們來(lái)看一下處理客戶(hù)端請(qǐng)求的方法:

  1. # 處理tcp連接def tcplink(conn, addr):  print("Accept new connection from %s:%s" % addr)  # 向客戶(hù)端發(fā)送歡迎消息  conn.send(b"Server: Welcome!\n")  while True:    conn.send(b"Server: What's your name?")    data = conn.recv(1024)    # 如果客戶(hù)端發(fā)送 exit 過(guò)來(lái)請(qǐng)求退出,結(jié)束循環(huán)    if data == b"exit":      conn.send(b"Server: Good bye!\n")      break    conn.send(b"Server: Hello %s!\n" % data)  # 關(guān)閉連接  conn.close()  print("Connection from %s:%s is closed" % addr) 

例子中,我們先想客戶(hù)端發(fā)送歡迎消息,然后詢(xún)問(wèn)客戶(hù)端名稱(chēng),收到名稱(chēng)后發(fā)送歡迎消息,直到接收到客戶(hù)端的 'exit' 命令,退出循環(huán),關(guān)閉連接。

實(shí)例

我們把上面的分步講解代碼合并起來(lái),形成一個(gè)可運(yùn)行的實(shí)例。

服務(wù)器端代碼:

  1. import socketimport threadingimport time# 處理tcp連接def tcplink(conn, addr):  print("Accept new connection from %s:%s" % addr)  # 向客戶(hù)端發(fā)送歡迎消息  conn.send(b"Server: Welcome!\n")  while True:    conn.send(b"Server: What's your name?")    data = conn.recv(1024)    # 如果客戶(hù)端發(fā)送 exit 過(guò)來(lái)請(qǐng)求退出,結(jié)束循環(huán)    if data == b"exit":      conn.send(b"Server: Good bye!\n")      break    conn.send(b"Server: Hello %s!\n" % data)  time.sleep(5)  # 關(guān)閉連接  conn.close()  print("Connection from %s:%s is closed" % addr)# 創(chuàng)建 sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 監(jiān)聽(tīng)端口s.bind(("127.0.0.1", 6000))# 設(shè)定等待連接的最大數(shù)量為5s.listen(5)print("Waiting for connection...")# 等待接收連接while True:  # 接受一個(gè)新連接  conn, addr = s.accept()  # 創(chuàng)建新線程來(lái)處理TCP連接  t = threading.Thread(target=tcplink, args=(conn, addr))  t.start() 

客戶(hù)端代碼:

  1. import socketimport time# 創(chuàng)建 sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 建立連接s.connect(("127.0.0.1", 6000))# 接收服務(wù)器消息print(s.recv(1024).decode())for data in [b'Michael', b'Tracy', b'Sarah']:  # 發(fā)送數(shù)據(jù)  s.send(data)  time.sleep(2)  # 打印接收到的數(shù)據(jù)  print(s.recv(1024).decode('utf-8'))  time.sleep(1)time.sleep(3)# 請(qǐng)求退出s.send(b'exit')time.sleep(2)print(s.recv(1024).decode('utf-8'))# 關(guān)閉連接s.close() 

注意,在代碼中,我加入了一些休眠(sleep)操作,主要是為了控制臺(tái)能夠順利打印出來(lái),不然程序運(yùn)行太快,打印順序和內(nèi)容有可能和預(yù)期不一樣。

先運(yùn)行服務(wù)器端代碼,然后再運(yùn)行客戶(hù)端代碼,我們可以看到服務(wù)器端控制臺(tái)打印內(nèi)容如下:

  1. #服務(wù)器端打印消息 Waitingforconnection... Acceptnewconnectionfrom127.0.0.1:53503 Connectionfrom127.0.0.1:53503isclosed 

客戶(hù)端控制臺(tái)打印內(nèi)容如下:

  1. #客戶(hù)端打印消息 Server:Welcome!Server:What'syourname? Server:HelloMichael! Server:What'syourname? Server:HelloTracy! Server:What'syourname? Server:HelloSarah! Server:What'syourname? Server:Goodbye! 

大家可以對(duì)照著打印內(nèi)容和代碼,體會(huì)一下服務(wù)器端和客戶(hù)端通信的原理。

總結(jié)

本文為大家介紹了 TCP 編程的基本原理和如何使用 Python 實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的 TCP 通信過(guò)程。通過(guò)介紹和實(shí)例,大家要在腦海中形成一個(gè) TCP 通信的過(guò)程,熟悉了這個(gè)過(guò)程是處理后續(xù)復(fù)雜通信需求的基礎(chǔ)。

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2009-08-24 17:20:13

C#網(wǎng)絡(luò)通信TCP連接

2020-01-14 11:19:38

網(wǎng)絡(luò)安全網(wǎng)絡(luò)安全技術(shù)周刊

2020-05-09 10:38:31

Python透視表數(shù)據(jù)

2010-04-20 14:06:56

Oracle SQL語(yǔ)

2024-02-02 08:25:34

隊(duì)列與棧Python數(shù)據(jù)結(jié)構(gòu)

2020-08-03 08:10:52

UDPTCP通信

2023-12-01 14:57:22

TCP連接

2009-06-24 16:26:17

MyEclipse

2010-06-09 14:36:44

TCP與UDP協(xié)議

2012-12-21 09:19:29

Google GO

2015-10-09 13:15:03

TCP網(wǎng)絡(luò)協(xié)議

2011-03-15 14:26:23

iptablesNAT

2011-03-15 09:10:47

iptablesNAT

2020-08-26 07:17:19

通信

2020-05-25 14:32:42

Python電子郵件自動(dòng)化

2009-06-19 14:44:04

ODBCMySQL

2023-12-26 01:07:03

TCP擁塞控制

2021-06-16 07:34:32

Pythonsocket庫(kù)Python基礎(chǔ)

2021-09-26 06:43:09

TCP連接Go

2009-07-17 17:41:25

JDBC連接SQL S
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)