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 socket

import time

IP_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 = 8009

BUF_SIZE = 1024

ADDR = (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 socketserver

import time

  

HOST = '127.0.0.1'

PORT = 8009

ADDR = (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 socket

HOST = '127.0.0.1'

PORT = 8009

ADDR = (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 python

Thu Sep 15 23:53:31 2016 b'hello python'

>>> hello pythontab

Thu 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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM