python進階之socket詳解

來源:互聯網
上載者:User
Socket的英文原義是“孔”或“插座”。作為BSD UNIX的進程通訊機制,通常也稱作"通訊端",用於描述IP地址和連接埠,是一個通訊鏈的控制代碼,可以用來實現不同虛擬機器或不同電腦之間的通訊。

網路上的兩個程式通過一個雙向的通訊串連實現資料的交換,這個串連的一端稱為一個socket。

建立網路通訊串連至少要一對連接埠號碼(socket)。socket本質是編程介面(API),對TCP/IP的封裝,TCP/IP也要提供可供程式員做網路開發所用的介面,這就是Socket編程介面;HTTP是轎車,提供了封裝或者顯示資料的具體形式;Socket是發動機,提供了網路通訊的能力。

下面來說一下python的socket。

1.socket模組

要使用socket.socket()函數來建立通訊端。其文法如下:

socket.socket(socket_family,socket_type,protocol=0)


socket_family可以是如下參數:


  socket.AF_INET IPv4(預設)

  socket.AF_INET6 IPv6


  socket.AF_UNIX 只能夠用於單一的Unix系統處理序間通訊


socket_type可以是如下參數:


  socket.SOCK_STREAM  流式socket , for TCP (預設)

  socket.SOCK_DGRAM   資料報式socket , for UDP


  socket.SOCK_RAW 原始通訊端,普通的通訊端無法處理ICMP、IGMP等網路報文,而SOCK_RAW可以;其次,SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始通訊端,可以通過IP_HDRINCL通訊端選項由使用者構造IP頭。

  socket.SOCK_RDM 是一種可靠的UDP形式,即保證交付資料報但不保證順序。SOCK_RAM用來提供對原始協議的低級訪問,在需要執行某些特殊操作時使用,如發送ICMP報文。SOCK_RAM通常僅限於進階使用者或管理員啟動並執行程式使用。

  socket.SOCK_SEQPACKET 可靠的連續資料包服務


protocol參數:


  0  (預設)與特定的地址家族相關的協議,如果是 0 ,則系統就會根據地址格式和套接類別,自動選擇一個合適的協議


2.通訊端對象內建方法


伺服器端通訊端函數


s.bind()   綁定地址(ip地址,連接埠)到通訊端,參數必須是元組的格式例如:s.bind(('127.0.0.1',8009))


s.listen(5)  開始監聽,5為最大掛起的串連數


s.accept()  被動接受用戶端串連,阻塞,等待串連


用戶端通訊端函數


s.connect()  串連伺服器端,參數必須是元組格式例如:s.connect(('127,0.0.1',8009))


公用用途的通訊端函數


s.recv(1024)  接收TCP資料,1024為一次資料接收的大小


s.send(bytes)  發送TCP資料,python3發送資料的格式必須為bytes格式


s.sendall()  完整發送資料,內部迴圈調用send


s.close()  關閉通訊端


執行個體1.簡單實現socket程式

server端

#!/usr/bin/env python# _*_ coding:utf-8 _*_import socketimport timeIP_PORT = ('127.0.0.1',8009)BUF_SIZE = 1024  tcp_server = socket.socket()tcp_server.bind(IP_PORT)tcp_server.listen(5)  while True:    print("waiting for connection...")    conn,addr = tcp_server.accept()    print("...connected from:",addr)    while True:        data = tcp_server.recv(BUF_SIZE)        if not data:break        tcp_server.send('[%s] %s'%(time.ctime(),data))  tcp_server.close()

以上代碼解釋:


1~4行


第一行是Unix的啟動資訊行,隨後匯入time模組和socket模組


5~10行


IP_PORT為全域變數聲明了IP地址和連接埠,表示bind()函數綁定在此地址上,把緩衝區的大小設定為1K,listen()函數表示最多允許多少個串連同時進來,後來的就會被拒絕掉


11~到最後一行


在進入伺服器的迴圈後,被動等待串連的到來。當有串連時,進入對話迴圈,等待用戶端發送資料。如果訊息為空白,表示用戶端已經退出,就跳出迴圈等待下一個串連到來。得到用戶端訊息後,在訊息前面加一個時間戳記然後返回。最後一行不會執行,因為迴圈不會退出所以服務端也不會執行close()。只是提醒不要忘記調用close()函數。


client端

#!/usr/bin/env python

# _*_ coding:utf-8 _*_import socket  HOST = '127.0.0.1'PORT = 8009BUF_SIZE = 1024ADDR = (HOST,PORT)  client = socket.socket()client.connect(ADDR)  while True:    data = input(">>> ")    if not data:break    client.send(bytes(data,encoding='utf-8'))    recv_data = client.recv(BUF_SIZE)    if not recv_data:break    print(recv_data.decode())      client.close()

5~11行

HOST和PORT變數表示伺服器的IP地址與連接埠號碼。由於示範是在同一台伺服器所以IP地址都是127.0.0.1,如果運行在其他伺服器上要做相應的修改。連接埠號碼要與伺服器端完全相同否則無法通訊。緩衝區大小還是1K。


用戶端通訊端在10行建立然後就去串連伺服器端


13~21行


用戶端也無限迴圈,用戶端的迴圈在以下兩個條件的任意一個發生後就退出:1.使用者輸入為空白的情況或者伺服器端響應的訊息為空白。否則用戶端會把使用者輸入的字串發送給伺服器進行處理,然後接收顯示伺服器返回來的帶有時間戳記的字串。


運行用戶端程式與服務端程式


以下是用戶端的輸入與輸出

[root@pythontab]# python client.py >>> hello python[Thu Sep 15 22:29:12 2016] b'hello python'


以下是服務端輸出

[root@pythontab]# python server.py waiting for connection......connected from: ('127.0.0.1', 55378)

3.socketserver模組

socketserver是標準庫中的一個進階別的模組。用於簡化實現網路用戶端與伺服器所需要的大量樣板代碼。模組中已經實現了一些可以使用的類。


執行個體1:使用socketserver實現與上面socket()執行個體一樣的功能


服務端程式碼

#!/usr/bin/env python# _*_ coding:utf-8 _*_import socketserverimport time  HOST = '127.0.0.1'PORT = 8009ADDR = (HOST,PORT)BUF_SIZE = 1024  class Myserver(socketserver.BaseRequestHandler):    def handle(self):        while True:            print("...connected from:",self.client_address)            data = self.request.recv(BUF_SIZE)            if not data:break            self.request.send(bytes("%s %s"%(time.ctime(),data)))  server = socketserver.ThreadingTCPServer(ADDR,Myserver)print("waiting for connection...")server.serve_forever()


11~17行


主要的工作在這裡。從socketserver的BaseRequestHandler類中派生出一個子類,並重寫handle()函數。


在有用戶端發進來的訊息的時候,handle()函數就會被調用。


19~21行


代碼的最後一部分用給定的IP地址和連接埠加上自訂處理請求的類(Myserver)。然後進入等待用戶端請求與處理用戶端請求的無限迴圈中。


用戶端程式代碼

import socketHOST = '127.0.0.1'PORT = 8009ADDR = (HOST,PORT)BUF_SIZE = 1024  client = socket.socket()client.connect(ADDR)  while True:    data = input(">>> ")    if not data:continue    client.send(bytes(data,encoding='utf-8'))    recv_data = client.recv(BUF_SIZE)    if not recv_data:break    print(recv_data.decode())  client.close()

執行服務端和用戶端代碼  


下面是用戶端輸出

[root@pythontab]# python socketclient.py >>> hello pythonThu Sep 15 23:53:31 2016 b'hello python'>>> hello pythontabThu Sep 15 23:53:49 2016 b'hello pythontab'


下面是服務端輸出

[root@pythontab]# python socketserver.py waiting for connection......connected from: ('127.0.0.1', 55385)...connected from: ('127.0.0.1', 55385)...connected from: ('127.0.0.1', 55385)...connected from: ('127.0.0.1', 55385)
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.