欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解python tcp編程

 更新時間:2020年08月24日 09:25:13   作者:Python技術  
這篇文章主要介紹了python tcp編程的相關資料,幫助大家更好的理解和學習python tcp編程,感興趣的朋友可以了解下

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

TCP 協(xié)議

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

Network Socket

我們來看看定義:

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

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

TCP 連接流程

上述快遞的例子中,寄快遞的我們可以叫做客戶端,收快遞的我們叫做服務器。專業(yè)點就是主動發(fā)起連接的一方叫做客戶端,被動響應的一方叫做服務器。例如,我們在瀏覽器中訪問百度搜索時,我們自己的電腦就是客戶端,瀏覽器會向百度的服務器發(fā)送連接請求,如果百度的服務器接受了我們的請求,那么一個 TCP 連接就建立起來了,后面就是百度向我們傳輸搜索結果了。

我們來看一個流程圖:

TCP服務器的建立可以歸納這幾步:

  • 創(chuàng)建 socket(套接字)
  • 綁定 socket 的 IP 地址和端口號
  • 監(jiān)聽客戶端的連接請求
  • 接受客戶端的連接請求
  • 與客戶端對話
  • 關閉連接

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

  • 創(chuàng)建 socket(套接字)
  • 連接服務器 socket
  • 與服務器對話
  • 關閉連接

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

TCP 客戶端

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

# 導入socket庫
import socket

# 創(chuàng)建一個socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立連接
s.connect(("127.0.0.1", 6000))

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

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

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

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

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

最后,我們需要關閉連接,很簡單:

s.close()

TCP 服務器

相比于客戶端,服務器端稍微復雜一些,需要先綁定一個 IP 地址和端口號,然后監(jiān)聽客戶端的請求,收到請求后丟到一個線程去處理。

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

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

接下來需要綁定監(jiān)聽地址和端口:

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

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

s.listen(5)

接下來就是無限循環(huán)等待客戶端的連接,直到有連接請求過來,就用一個線程去處理:

while True:
  # 接受一個新連接
  sock, addr = s.accept()
  # 創(chuàng)建新線程來處理TCP連接
  t = threading.Thread(target=tcplink, args=(sock, addr))
  t.start()

這里為什么需要多線程處理呢?想象一下菜鳥驛站,如果里面只有一個人的話,那么多個人寄件就需要排隊,一個個來;但是如果有多個人的話,那么每個人都可以處理一個寄件請求。

我們來看一下處理客戶端請求的方法:

# 處理tcp連接
def tcplink(conn, addr):
  print("Accept new connection from %s:%s" % addr)
  # 向客戶端發(fā)送歡迎消息
  conn.send(b"Server: Welcome!\n")
  while True:
    conn.send(b"Server: What's your name?")

    data = conn.recv(1024)
    # 如果客戶端發(fā)送 exit 過來請求退出,結束循環(huán)
    if data == b"exit":
      conn.send(b"Server: Good bye!\n")
      break
    conn.send(b"Server: Hello %s!\n" % data)

  # 關閉連接
  conn.close()
  print("Connection from %s:%s is closed" % addr)

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

實例

我們把上面的分步講解代碼合并起來,形成一個可運行的實例。

服務器端代碼:

import socket
import threading
import time

# 處理tcp連接
def tcplink(conn, addr):
  print("Accept new connection from %s:%s" % addr)
  # 向客戶端發(fā)送歡迎消息
  conn.send(b"Server: Welcome!\n")
  while True:
    conn.send(b"Server: What's your name?")

    data = conn.recv(1024)
    # 如果客戶端發(fā)送 exit 過來請求退出,結束循環(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)
  # 關閉連接
  conn.close()
  print("Connection from %s:%s is closed" % addr)


# 創(chuàng)建 socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 監(jiān)聽端口
s.bind(("127.0.0.1", 6000))
# 設定等待連接的最大數(shù)量為5
s.listen(5)
print("Waiting for connection...")
# 等待接收連接
while True:
  # 接受一個新連接
  conn, addr = s.accept()
  # 創(chuàng)建新線程來處理TCP連接
  t = threading.Thread(target=tcplink, args=(conn, addr))
  t.start()

客戶端代碼:

import socket
import time

# 創(chuàng)建 socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 建立連接
s.connect(("127.0.0.1", 6000))

# 接收服務器消息
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)
# 請求退出
s.send(b'exit')
time.sleep(2)
print(s.recv(1024).decode('utf-8'))

# 關閉連接
s.close()

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

先運行服務器端代碼,然后再運行客戶端代碼,我們可以看到服務器端控制臺打印內容如下:

# 服務器端打印消息
Waiting for connection...
Accept new connection from 127.0.0.1:53503
Connection from 127.0.0.1:53503 is closed

客戶端控制臺打印內容如下:

# 客戶端打印消息
Server: Welcome!
Server: What's your name?
Server: Hello Michael!
Server: What's your name?
Server: Hello Tracy!
Server: What's your name?
Server: Hello Sarah!
Server: What's your name?
Server: Good bye!

大家可以對照著打印內容和代碼,體會一下服務器端和客戶端通信的原理。

總結

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

文中實例代碼

以上就是詳解python tcp編程的詳細內容,更多關于python tcp編程的資料請關注腳本之家其它相關文章!

相關文章

最新評論