Python網路編程

來源:互聯網
上載者:User

標籤:

thanks to?http://www.liaoxuefeng.com

網路中的各種協議

1. IP協議:IP協議是重要的網路通訊協定,對應了每台電腦的唯一標識:IP地址,實際上就是每台計算機連結網路的介面,通常是網卡。IP協議負責把資料從一台電腦通過網路傳到另外一台電腦,資料被分割成小塊,然後通過IP包(IP包包含資料、源IP地址和目標IP地址、源連接埠和目標連接埠),通過兩台電腦之間串連的線路發送出去,但是IP協議並不保證資料準確到達,同時不保證順序到達。

2. TCP協議:TCP協議建立在IP協議之上,將兩台電腦通過握手,建立可靠的串連,並且對每個IP包編號,確保資料順序可靠到達,如果發生丟包,則自動重發。在TCP協議的基礎上,有更多進階的協議:HTTP、SMTP等常見協議。

3. UDP協議:UDP協議不需要建立可靠串連,直接發送包,但是不保證能夠準確到達。UDP協議的優點就是速度快,在某一些不要求可靠達到的資料,可以使用UDP協議。

TCP用戶端編程

建立網路連接的基礎是建立一個socket,socket指定了目標電腦的IP地址和連接埠號碼,以及協議類型。

在用戶端發起TCP串連,需要指定socket的協議為TCP/IP協議:

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

socket類在執行個體化時,接受4個參數:family=AF_INET,type=SOCK_STREAM,proto=0,_sock=None

第四個參數_sock是一個_realsocket 對象,如果指定了該對象,則會從該對象中繼承family、type、photo屬性,並且繼承delegate方法:("recv", "recvfrom", "recv_into", "recvfrom_into","send", "sendto”)。 _realsocket類是c實現的,所以只能看到標頭檔_realsocket.py。

前三個參數依次為:地址協議、流協議、介面協議(?)

建立了socket對象之後,通過connet方法建立串連:

s.connet((‘www.baidu.com’),80)

connet方法要求傳入一個地址,如果是IP類的socket,則需要傳入一個元組,包含地址(會被dns解析)和連接埠

建立串連之後,就可以發送請求。TCP協議是雙向串連的,雙方都可以發送資料,但是具體發送的規則有更加高層的協議,如http協議決定(http協議規則:必須有用戶端發送請求給伺服器,伺服器收到後才發資料給用戶端):

s.send(‘GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n‘)

如上發送一條HTTP 1.1協議請求,擷取百度首頁的內容,請求發送後,百度伺服器就會響應請求,並且向我們發送首頁的內容,通過recv方法接收伺服器發來的資訊,並且指定單次接收的最大位元組數:

buffer = []
while True:
? ??d = s.recv(1024)
? ? if d:
? ? ? ? buffer.append(d)
? ? else:
? ? ? ? break
data = ‘‘.join(buffer)

如上data中包含了從伺服器中接收的全部資料,包括一個http頭,和真正需要接收的網頁本身,再發送請求時,我們以兩個斷行符號換行來分割http頭和接收到的網頁,所以將其從新分離即可得到百度首頁的內容:

header, html = data.split(‘\r\n\r\n‘, 1)

將其寫到檔案中:

with open(‘baidu.html‘, ‘wb‘) as f:
? ? f.write(html)

用瀏覽器開啟baidu.html,即可看到百度首頁的內容了

總指令碼如下:

__author__ = ‘liangzb‘
import socket
s = socket.socket(family=2,type=socket.SOCK_STREAM)
print type(s.family)
s2 = socket.socket(_sock=s)
print s2.family
s.connect((‘www.baidu.com‘,80))
s.send(‘GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n‘)
buffer = []
while True:
? ? d = s.recv(1024)
? ? if d:
? ? ? ? buffer.append(d)
? ? else:
? ? ? ? breakdata = ‘‘.join(buffer)
s.close()
# print data
header, html = data.split(‘\r\n\r\n‘, 1)
# print header
with open(‘baidu.html‘, ‘w‘) as f:
? ? f.write(html)

TCP服務端編程

伺服器和用戶端的區別就是伺服器需要接受來自不同用戶端的請求,並且分別作出響應,為了實現該過程,需要先建立一個綁定,綁定伺服器的ip地址和連接埠:

s.bind((‘127.0.0.1‘, 9999))

之後,調用listen方法監聽來自該連接埠訊息,傳入參數指定最大等待串連的數量:

listen(max_connection)

接下來,伺服器應該保持運行狀態,啟用一個死迴圈來接收來自用戶端的串連,accept方法可以接收來自用戶端的串連,並且返回用戶端的socket對象和地址。需要注意的是,對於每一個請求,都應該新開一條線程或者進程(win下只能開線程)來處理:

while True:
? ? sock, addr = s.accept()
? ? t = threading.Thread(target=tcplink, args=(sock, addr))
? ? t.start()

編寫處理函數來響應請求:

def tcplink(sock, addr):
? ? print ‘Accept new connection from %s:%s...‘ % addr
? ? sock.send(‘Welcome!‘)
? ? while True:
? ? ? ? data = sock.recv(1024)
? ? ? ? time.sleep(1)
? ? ? ? if data == ‘exit‘ or not data:
? ? ? ? ? ? break
? ? ? ? sock.send(‘Hello, %s!‘ % data)
? ? sock.close()
? ? print ‘Connection from %s:%s closed.‘ % addr

服務端總指令碼如下:

__author__ = ‘liangzb‘
import threading
import socket
import time

def tcplink(sock, addr):
? ? print ‘Accept new connection from %s:%s...‘ % addr
? ? sock.send(‘Welcome!‘)
? ? while True:
? ? ? ? data = sock.recv(1024)
? ? ? ? time.sleep(1)
? ? ? ? if data == ‘exit‘ or not data:
? ? ? ? ? ? break
? ? ? ? sock.send(‘Hello, %s!‘ % data)
? ? sock.close()
? ? print ‘Connection from %s:%s closed.‘ % addr

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((‘127.0.0.1‘, 9999))
s.listen(5)
print ‘Waiting for connection...‘

while True:
? ? sock, addr = s.accept()
? ? t = threading.Thread(target=tcplink, args=(sock, addr))
? ? t.start()

可以通過另外一個用戶端給該服務端發送訊息來測試,注意,這裡綁定的ip地址是127.0.0.1,是本地地址,只能是本機訪問

用戶端程式參考:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((‘127.0.0.1‘, 9999))
print s.recv(1024)
for data in [‘Michael‘, ‘Tracy‘, ‘Sarah‘]:
? ? s.send(data)
? ? print s.recv(1024)
s.send(‘exit‘)
s.close()

原始碼來自:http://www.liaoxuefeng.com/ ,thanks to liaoxuefeng for share

運行效果:

UDP編程

協議是不確定串連可靠性的,socket流協議應該設定為:SOCK_DGRAM:

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

由於UDP協議的特徵,UDP的服務端在建立串連時,不需要調用listen方法,而是直接對接收到的請求作出回應,而用戶端的資訊,則又recvfrom方法返回的元組得到。在發送訊息時,也只需要通過sendto方法,將用戶端的地址作為第二個參數傳入。

而在UDP協議的用戶端,同樣不需要先經過串連,而是直接將準備好的請求發送到某一個地址,利用sendto方法,將服務端的地址作為第二個參數傳入,其他接收方式則和TCP相同。

Python網路編程

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.