首頁  >  文章  >  後端開發  >  python學習進階之socket詳細介紹

python學習進階之socket詳細介紹

高洛峰
高洛峰原創
2017-03-19 14:57:521258瀏覽

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-#4(預設)

#  socket.AF_INET6 IPv6

  socket.AF_UNIX 只能夠用於單一的Unix系統進程間通訊

socket_type可以是以下參數:

 流式串流. 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)

以上是python學習進階之socket詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn