日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python网络编程项目_Python网络编程攻略

發(fā)布時(shí)間:2025/3/15 python 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python网络编程项目_Python网络编程攻略 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

第1章套接字、IPv4和簡單的客戶端/服務(wù)器編程

本章攻略:

打印設(shè)備名和IPv4地址

獲取遠(yuǎn)程設(shè)備的IP地址

將IPv4地址轉(zhuǎn)換成不同的格式

通過指定的端口和協(xié)議找到服務(wù)名

主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序之間相互轉(zhuǎn)換

設(shè)定并獲取默認(rèn)的套接字超時(shí)時(shí)間

優(yōu)雅地處理套接字錯(cuò)誤

修改套接字發(fā)送和接收的緩沖區(qū)大小

把套接字改成阻塞或非阻塞模式

重用套接字地址

從網(wǎng)絡(luò)時(shí)間服務(wù)器上獲取并打印當(dāng)前時(shí)間

編寫一個(gè)SNTP客戶端

編寫一個(gè)簡單的回顯客戶端/服務(wù)器應(yīng)用

1.1簡介

本章通過一些簡單的攻略介紹Python的核心網(wǎng)絡(luò)庫。Python的socket模塊提供了類方法和實(shí)例方法,二者的區(qū)別在于使用類方法時(shí)不需要創(chuàng)建套接字對象實(shí)例。這是一種很直觀的方法。例如,打印設(shè)備的IP地址不需要創(chuàng)建套接字對象,而只需調(diào)用套接字的類方法。但是,如果要把數(shù)據(jù)發(fā)送給服務(wù)器程序,那么創(chuàng)建一個(gè)套接字對象來處理具體的操作則更加自然。本章介紹的攻略可以分成如下三類:

前幾個(gè)攻略使用類方法獲取關(guān)于主機(jī)、網(wǎng)絡(luò)以及目標(biāo)服務(wù)的有用信息;

隨后的幾個(gè)攻略使用實(shí)例方法,演示了常用的套接字操作,例如處理套接字超時(shí)、緩沖區(qū)大小和阻塞模式等;

.  最后,結(jié)合使用類方法和實(shí)例方法開發(fā)客戶端,執(zhí)行一些實(shí)際的任務(wù),例如使設(shè)備時(shí)間與網(wǎng)絡(luò)服務(wù)器同步,編寫通用的客戶端/服務(wù)器腳本。

你可以使用本章演示的方法編寫自己的客戶端/服務(wù)器應(yīng)用。

1.2打印設(shè)備名和IPv4地址

有時(shí),你需要快速查看設(shè)備的某些信息,例如主機(jī)名、IP地址和網(wǎng)絡(luò)接口的數(shù)量等。這些信息使用Python腳本很容易獲取。

1.2.1準(zhǔn)備工作

編寫代碼之前先要在設(shè)備上安裝Python。大多數(shù)Linux發(fā)行版都預(yù)裝了Python。如果使用微軟Windows操作系統(tǒng),可以從Python的網(wǎng)站上下載二進(jìn)制文件:http://www.python.org/download/。

要了解系統(tǒng)是否已經(jīng)安裝了Python,可以查閱操作系統(tǒng)的文檔。在設(shè)備上安裝好Python之后,可以在命令行中輸入python,嘗試打開Python解釋器。輸入python后應(yīng)該顯示解釋器提示符))),具體的輸出如下所示:

~$ python

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24)

[GCC 4.5.2] on linux2

Type "help", "copyright", "credits" or "license" for more information. )))

1.2.2實(shí)戰(zhàn)演練

這個(gè)攻略很簡短,可以直接寫在Python解釋器中。

首先,使用下面的命令導(dǎo)入Python中的socket庫:

))) import socket

然后,調(diào)用socket庫提供的gethostname()方法,把結(jié)果保存在一個(gè)變量中,如下所示:

))) host_name = socket.gethostname()

))) print "Host name: %s" %host_name

Host name: debian6

))) print "IP address: %s" %socket.gethostbyname(host_name)

IP address: 127.0.1.1

這些操作可以使用內(nèi)置的類方法,定義成一個(gè)獨(dú)立的函數(shù)print_machine_info()。

我們要在常用的__main__代碼塊中調(diào)用這個(gè)函數(shù)。運(yùn)行時(shí),Python會為某些內(nèi)部變量賦值, 例如__name__。在這里,__name__表示調(diào)用程序的進(jìn)程名。如果在命令行中運(yùn)行腳本(如后面的命令所示),__name__的值是__main__。但是,如果在其他腳本中導(dǎo)入,情況就不同了。也就是說,如果在命令行中調(diào)用這個(gè)模塊,會自動運(yùn)行print_machine_info()函數(shù);如果在其他腳本中導(dǎo)入,用戶就要手動調(diào)用這個(gè)函數(shù)。

代碼清單1-1展示了如何獲取設(shè)備的信息,如下所示:

#!/usr/bin/env python

# Python Network Programming Cookbook -- Chapter -1

# This program is optimized for Python 2.7. It may run on any

# other Python version with/without modifications.

import socket

def print_machine_info():

host_name = socket.gethostname()

ip_address = socket.gethostbyname(host_name)

print "Host name: %s" % host_name

print "IP address: %s" % ip_address

if __name__ == '__main__':

print_machine_info()

若想運(yùn)行這個(gè)腳本,要在命令行中指定源碼文件,如下所示:

$ python 1_1_local_machine_info.py

在我的設(shè)備上,顯示了如下輸出:

Host name: debian6

IP address: 127.0.0.1

在你的設(shè)備上,輸出的內(nèi)容根據(jù)系統(tǒng)的主機(jī)配置會有所不同。

1.2.3原理分析

import socket語句導(dǎo)入Python提供的一個(gè)核心網(wǎng)絡(luò)庫。然后調(diào)用兩個(gè)工具函數(shù):gethostname()和gethostbyname(host_name)。在命令行中可以輸入help(socket.geth- ostname)查看幫助信息,或者在瀏覽器中訪問http://docs.python.org/3/library/socket.html。在命令行中查看這兩個(gè)函數(shù)的幫助信息,得到的輸出如下:

gethostname(...)

gethostname() -) string

Return the current host name.

gethostbyname(...)

gethostbyname(host) -) address

Return the IP address (a string of the form '255.255.255.255') for a host.

第一個(gè)函數(shù)沒有參數(shù),返回所在主機(jī)或本地主機(jī)的名字。第二個(gè)函數(shù)接收一個(gè)參數(shù)hostname,返回對應(yīng)的IP地址。

1.3獲取遠(yuǎn)程設(shè)備的IP地址

有時(shí)需要把設(shè)備的主機(jī)名轉(zhuǎn)換成對應(yīng)的IP地址,例如快速查詢域名。本攻略介紹一個(gè)簡單的函數(shù)來完成這一操作。

1.3.1實(shí)戰(zhàn)演練

如果想知道遠(yuǎn)程設(shè)備的IP地址,可以使用內(nèi)置的庫函數(shù)gethostbyname(),其參數(shù)是遠(yuǎn)程設(shè)備的主機(jī)名。

這里,我們要調(diào)用的是類函數(shù)gethostbyname()。讓我們來看一下這個(gè)簡短的代碼片段。

代碼清單1-2展示了如何獲取遠(yuǎn)程設(shè)備的IP地址,如下所示:

#!/usr/bin/env python

# Python Network Programming Cookbook -- Chapter – 1

# This program is optimized for Python 2.7.

# It may run on any other version with/without modifications.

import socket

def get_remote_machine_info():

remote_host = 'www.python.org'

try:

print "IP address: %s" %socket.gethostbyname(remote_host)

except socket.error, err_msg:

print "%s: %s" %(remote_host, err_msg)

if __name__ == '__main__':

get_remote_machine_info()

運(yùn)行上述代碼會得到以下輸出:

$ python 1_2_remote_machine_info.py

IP address of www.python.org: 82.94.164.162

1.3.2原理分析

這個(gè)攻略把gethostbyname()方法包裝在用戶定義的get_remote_machine_info()函數(shù)中,還引入了異常處理的概念。如上述代碼所示,我們把主要的函數(shù)調(diào)用放在try-except塊中,這就意味著,如果執(zhí)行函數(shù)gethostbyname()的過程中發(fā)生了錯(cuò)誤,這個(gè)錯(cuò)誤將由try-except塊處理。

假如我們修改remote_host參數(shù)的值,把www.python.org改成一個(gè)不存在的域名,例如www.pytgo.org,然后執(zhí)行下述命令:

$ python 1_2_remote_machine_info.py

www.pytgo.org: [Errno -5] No address associated with hostname

try-except塊捕獲了錯(cuò)誤,并向用戶顯示了一個(gè)錯(cuò)誤消息,說明域名www.pytgo.org沒有對應(yīng)的IP地址。

1.4將IPv4地址轉(zhuǎn)換成不同的格式

如果要使用低層網(wǎng)絡(luò)函數(shù),有時(shí)普通的字符串形式的IP地址并不是很有用,需要把它們轉(zhuǎn)換成打包后的32位二進(jìn)制格式。

1.4.1實(shí)戰(zhàn)演練

Python的socket庫提供了很多用來處理不同IP地址格式的函數(shù),這里我們使用其中的兩個(gè):inet_aton()和inet_ntoa()。

我們來定義convert_ip4_address()函數(shù),調(diào)用inet_aton()和inet_ntoa()轉(zhuǎn)換IP地址。我們要使用兩個(gè)示例IP地址:127.0.0.1和192.168.0.1。

代碼清單1-3展示了如何定義convert_ip4_address()函數(shù),如下所示:

#!/usr/bin/env python

# Python Network Programming Cookbook -- Chapter – 1

# This program is optimized for Python 2.7.

# It may run on any other version with/without modifications.

import socket

from binascii import hexlify

def convert_ip4_address():

for ip_addr in ['127.0.0.1', '192.168.0.1']:

packed_ip_addr = socket.inet_aton(ip_addr)

unpacked_ip_addr = socket.inet_ntoa(packed_ip_addr)

print "IP Address: %s =) Packed: %s, Unpacked: %s"\

%(ip_addr, hexlify(packed_ip_addr), unpacked_ip_addr)

if __name__ == '__main__':

convert_ip4_address()

現(xiàn)在,運(yùn)行這個(gè)攻略,會看到以下輸出:

$ python 1_3_ip4_address_conversion.py

IP Address: 127.0.0.1 =) Packed: 7f000001, Unpacked: 127.0.0.1

IP Address: 192.168.0.1 =) Packed: c0a80001, Unpacked: 192.168.0.1

1.4.2原理分析

在這個(gè)攻略中,使用for-in語句把兩個(gè)字符串形式的IP地址轉(zhuǎn)換成打包后的32位二進(jìn)制格式,而且還調(diào)用了binascii模塊中的hexlify函數(shù),以十六進(jìn)制形式表示二進(jìn)制數(shù)據(jù)。

1.5通過指定的端口和協(xié)議找到服務(wù)名

如果想找到網(wǎng)絡(luò)服務(wù),最好知道該服務(wù)運(yùn)行在TCP或UDP協(xié)議的哪個(gè)端口上。

1.5.1準(zhǔn)備工作

如果知道網(wǎng)絡(luò)服務(wù)使用的端口,可以調(diào)用socket庫中的getservbyport()函數(shù)來獲取服務(wù)的名字。調(diào)用這個(gè)函數(shù)時(shí)可以根據(jù)情況決定是否提供協(xié)議名。

1.5.2實(shí)戰(zhàn)演練

我們來定義find_service_name()函數(shù),在Python的for-in循環(huán)中調(diào)用函數(shù)getservbyport(),解析幾個(gè)端口,例如80和25。

代碼清單1-4展示了如何定義find_service_name()函數(shù),如下所示:

#!/usr/bin/env python

# Python Network Programming Cookbook -- Chapter - 1

# This program is optimized for Python 2.7.

# It may run on any other version with/without modifications.

import socket

def find_service_name():

protocolname = 'tcp'

for port in [80, 25]:

print "Port: %s =) service name: %s" %(port, socket.getservbyport(port, protocolname))

print "Port: %s =) service name: %s" %(53, socket.getservbyport(53, 'udp'))

if __name__ == '__main__':

find_service_name()

運(yùn)行這個(gè)腳本,會看到如下輸出:

$ python 1_4_finding_service_name.py

Port: 80 =) service name: http

Port: 25 =) service name: smtp

Port: 53 =) service name: domain

1.5.3原理分析

在這個(gè)攻略中,使用for-in語句遍歷一組變量。在每次遍歷中,獲取端口對應(yīng)的服務(wù)名。

1.6主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序之間相互轉(zhuǎn)換

編寫低層網(wǎng)絡(luò)應(yīng)用時(shí),或許需要處理通過電纜在兩臺設(shè)備之間傳送的低層數(shù)據(jù)。在這種操作中,需要把主機(jī)操作系統(tǒng)發(fā)出的數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡(luò)格式,或者做逆向轉(zhuǎn)換,因?yàn)檫@兩種數(shù)據(jù)的表示方式不一樣。

1.6.1實(shí)戰(zhàn)演練

Python的socket庫提供了將數(shù)據(jù)在網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序之間相互轉(zhuǎn)換的函數(shù)。你可能想了解這些函數(shù),例如ntohl()和htonl()。

我們來定義convert_integer()函數(shù),調(diào)用ntohl()和htonl()類函數(shù)來轉(zhuǎn)換不同格式的數(shù)據(jù)。

代碼清單1-5展示了如何定義convert_integer()函數(shù),如下所示:

#!/usr/bin/env python

# Python Network Programming Cookbook -- Chapter -1

# This program is optimized for Python 2.7.

# It may run on any other version with/without modifications.

import socket

def convert_integer():

data = 1234

# 32-bit

print "Original: %s =) Long host byte order: %s, Network byte order: %s"\

%(data, socket.ntohl(data), socket.htonl(data))

# 16-bit

print "Original: %s =) Short host byte order: %s, Network byte order: %s"\

%(data, socket.ntohs(data), socket.htons(data))

if __name__ == '__main__':

convert_integer()

運(yùn)行這個(gè)攻略,會看到以下輸出:

$ python 1_5_integer_conversion.py

Original: 1234 =) Long host byte order: 3523477504, Network byte order: 3523477504

Original: 1234 =) Short host byte order: 53764, Network byte order: 53764

1.6.2原理分析

在這個(gè)攻略中,我們以整數(shù)為例,演示了如何把它轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序。socket庫中的類函數(shù)ntohl()把網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成了長整形主機(jī)字節(jié)序。函數(shù)名中的n表示網(wǎng)絡(luò);h表示主機(jī);l表示長整形;s表示短整形,即16位。

1.7設(shè)定并獲取默認(rèn)的套接字超時(shí)時(shí)間

有時(shí),你需要處理socket庫某些屬性的默認(rèn)值,例如套接字超時(shí)時(shí)間。

1.7.1實(shí)戰(zhàn)演練

你可以創(chuàng)建一個(gè)套接字對象實(shí)例,調(diào)用gettimeout()方法獲取默認(rèn)的超時(shí)時(shí)間,調(diào)用settimeout()方法設(shè)定一個(gè)超時(shí)時(shí)間。這種操作在開發(fā)服務(wù)器應(yīng)用時(shí)很有用。

在test_socket_timeout()函數(shù)中,首先創(chuàng)建一個(gè)套接字對象,然后使用讀取或者設(shè)定實(shí)例方法處理超時(shí)時(shí)間。

代碼清單1-6展示了如何定義test_socket_timeout()函數(shù),如下所示:

#!/usr/bin/env python

# Python Network Programming Cookbook -- Chapter - 1

# This program is optimized for Python 2.7. It may run on any

# other Python version with/without modifications.

import socket

def test_socket_timeout():

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

print "Default socket timeout: %s" %s.gettimeout()

s.settimeout(100)

print "Current socket timeout: %s" %s.gettimeout()

if __name__ == '__main__':

test_socket_timeout()

運(yùn)行上述代碼后,你會看到它是如何修改默認(rèn)超時(shí)時(shí)間的,如下所示:

$ python 1_6_socket_timeout.py

Default socket timeout: None

Current socket timeout: 100.0

1.7.2原理分析

在這段代碼片段中,首先創(chuàng)建了一個(gè)套接字對象。套接字構(gòu)造方法的第一個(gè)參數(shù)是地址族,第二個(gè)參數(shù)是套接字類型。然后,調(diào)用gettimeout()方法獲取套接字超時(shí)時(shí)間,再調(diào)用settimeout()方法修改超時(shí)時(shí)間。傳給settimeout()方法的參數(shù)可以是秒數(shù)(非負(fù)浮點(diǎn)數(shù))也可以是None。這個(gè)方法在處理阻塞式套接字操作時(shí)使用。如果把超時(shí)時(shí)間設(shè)為None,則禁用了套接字操作的超時(shí)檢測。

1.8優(yōu)雅地處理套接字錯(cuò)誤

在網(wǎng)絡(luò)應(yīng)用中,經(jīng)常會遇到這種情況:一方嘗試連接,但另一方由于網(wǎng)絡(luò)媒介失效或者其他原因無法響應(yīng)。Python的socket庫提供了一個(gè)方法,能通過socket.error異常優(yōu)雅地處理套接字錯(cuò)誤。在這個(gè)攻略中會舉幾個(gè)例子。

1.8.1實(shí)戰(zhàn)演練

我們來編寫幾個(gè)try-except代碼塊,每個(gè)塊對應(yīng)一種可能發(fā)生的錯(cuò)誤。為了獲取用戶輸入,可以使用argparse模塊。這個(gè)模塊的功能很強(qiáng)大,而不僅是可以使用sys.argv解析命令行參數(shù)。這些try-except代碼塊分別演示了常見的套接字操作,例如創(chuàng)建套接字對象、連接服務(wù)器、發(fā)送數(shù)據(jù)和等待應(yīng)答。

下述攻略使用幾行代碼演示了如何處理異常。

代碼清單1-7展示了如何處理socket.error異常,如下所示:

#!/usr/bin/env python

# Python Network Programming Cookbook -- Chapter – 1

# This program is optimized for Python 2.7. It may run on any

# other Python version with/without modifications.

import sys

import socket

import argparse

def main():

# setup argument parsing

parser = argparse.ArgumentParser(description='Socket Error Examples')

parser.add_argument('--host', action="store", dest="host", required=False)

parser.add_argument('--port', action="store", dest="port", type=int, required=False)

parser.add_argument('--file', action="store", dest="file", required=False)

given_args = parser.parse_args()

host = given_args.host

port = given_args.port

filename = given_args.file

# First try-except block -- create socket

try:

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

except socket.error, e:

print "Error creating socket: %s" % e

sys.exit(1)

# Second try-except block -- connect to given host/port

try:

s.connect((host, port))

except socket.gaierror, e:

print "Address-related error connecting to server: %s" % e

sys.exit(1)

except socket.error, e:

print "Connection error: %s" % e

sys.exit(1)

# Third try-except block -- sending data

try:

s.sendall("GET %s HTTP/1.0\r\n\r\n" % filename)

except socket.error, e:

print "Error sending data: %s" % e

sys.exit(1)

while 1:

# Fourth tr-except block -- waiting to receive data from remote host

try:

buf = s.recv(2048)

except socket.error, e:

print "Error receiving data: %s" % e

sys.exit(1)

if not len(buf):

break

# write the received data

sys.stdout.write(buf)

if __name__ == '__main__':

main()

1.8.2原理分析

在Python中,可以使用argparse模塊把命令行參數(shù)傳入腳本以及在腳本中解析命令行參數(shù)。這個(gè)模塊在Python 2.7中可用。如果使用較舊版本的Python,這個(gè)模塊可以到“Python包索引”(Python Package Index,簡稱PyPI)中獲取,使用easy_install或pip安裝。

這個(gè)攻略用到了三個(gè)命令行參數(shù):主機(jī)名、端口號和文件名。上述腳本的使用方法如下:

$ python 1_7_socket_errors.py –host=

如果提供的主機(jī)不存在,這個(gè)腳本會輸出如下錯(cuò)誤:

$ python 1_7_socket_errors.py --host=www.pytgo.org --port=8080 --file=1_7_socket_errors.py

Address-related error connecting to server: [Errno -5] No address associated with hostname

如果某個(gè)端口上沒有服務(wù),你卻嘗試連接到這個(gè)端口,則這個(gè)腳本會拋出連接超時(shí)異常,如下所示:

$ python 1_7_socket_errors.py --host=www.python.org --port=8080 --file=1_7_socket_errors.py

這個(gè)命令會返回如下錯(cuò)誤,因?yàn)橹鳈C(jī)www.python.org監(jiān)聽的不是端口8080:

Connection error: [Errno 110] Connection timed out

不過,如果向正確的主機(jī)、正確的端口發(fā)起隨意的請求,應(yīng)用層可能無法捕獲這一異常。例如,運(yùn)行下述腳本,不會返回錯(cuò)誤,但輸出的HTML代碼說明了腳本的問題:

$ python 1_7_socket_errors.py --host=www.python.org --port=80 --file=1_7_socket_errors.py

HTTP/1.1 404 Not found

Server: Varnish

Retry-After: 0

content-type: text/html

Content-Length: 77

Accept-Ranges: bytes

Date: Thu, 20 Feb 2014 12:14:01 GMT

Via: 1.1 varnish

Age: 0

Connection: close

)

unknown domain: ))

這個(gè)攻略用到了四個(gè)try-except塊。除第二個(gè)塊處理socket.gaierror異常之外,其他塊都處理socket.error異常。socket.gaierror是地址相關(guān)的錯(cuò)誤。除此之外還有兩種異常:socket.herror,C API中拋出的異常;如果在套接字中使用settimeout()方法,套接字超時(shí)后會拋出socket.timeout異常。

1.9修改套接字發(fā)送和接收的緩沖區(qū)大小

很多情況下,默認(rèn)的套接字緩沖區(qū)大小可能不夠用。此時(shí),可以將默認(rèn)的套接字緩沖區(qū)大小改成一個(gè)更合適的值。

1.9.1實(shí)戰(zhàn)演練

我們要使用套接字對象的setsockopt()方法修改默認(rèn)的套接字緩沖區(qū)大小。

首先,定義兩個(gè)常量:SEND_BUF_SIZE和RECV_BUF_SIZE。然后在一個(gè)函數(shù)中調(diào)用套接字實(shí)例的setsockopt()方法。修改之前,最好先檢查緩沖區(qū)大小是多少。注意,發(fā)送和接收的緩沖區(qū)大小要分開設(shè)定。

代碼清單1-8展示了如何修改套接字的發(fā)送和接收緩沖區(qū)大小,如下所示:

#!/usr/bin/env python

# Python Network Programming Cookbook -- Chapter – 1

# This program is optimized for Python 2.7. It may run on any

# other Python version with/without modifications.

import socket

SEND_BUF_SIZE = 4096

RECV_BUF_SIZE = 4096

def modify_buff_size():

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

# Get the size of the socket's send buffer

bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)

print "Buffer size [Before]:%d" %bufsize

sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)

sock.setsockopt(

socket.SOL_SOCKET,

socket.SO_SNDBUF,

SEND_BUF_SIZE)

sock.setsockopt(

socket.SOL_SOCKET,

socket.SO_RCVBUF,

RECV_BUF_SIZE)

bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)

print "Buffer size [After]:%d" %bufsize

if __name__ == '__main__':

modify_buff_size()

運(yùn)行上述腳本后,會顯示修改套接字緩沖區(qū)大小前后的變化。根據(jù)你所用操作系統(tǒng)的本地設(shè)定,得到的輸出可能有所不同:

$ python 1_8_modify_buff_size.py

Buffer size [Before]:16384

Buffer size [After]:8192

1.9.2原理分析

在套接字對象上可調(diào)用方法getsockopt()和setsockopt()分別獲取和修改套接字對象的屬性。setsockopt()方法接收三個(gè)參數(shù):level、optname和value。其中,optname是選項(xiàng)名,value是該選項(xiàng)的值。第一個(gè)參數(shù)所用的符號常量(SO_*等)可在socket模塊中查看。

1.10把套接字改成阻塞或非阻塞模式

默認(rèn)情況下,TCP套接字處于阻塞模式中。也就是說,除非完成了某項(xiàng)操作,否則不會把控制權(quán)交還給程序。例如,調(diào)用connect() API后,連接操作會阻止程序繼續(xù)往下執(zhí)行,直到連接成功為止。很多情況下,你并不想讓程序一直等待服務(wù)器響應(yīng)或者有異常終止操作。例如,如果編寫了一個(gè)網(wǎng)頁瀏覽器客戶端連接服務(wù)器,你應(yīng)該考慮提供取消功能,以便在操作過程中取消連接。這時(shí)就要把套接字設(shè)置為非阻塞模式。

1.10.1實(shí)戰(zhàn)演練

我們來看一下在Python中有哪些選項(xiàng)。在Python中,套接字可以被設(shè)置為阻塞模式或者非阻塞模式。在非阻塞模式中,調(diào)用API后,例如send()或recv()方法,如果遇到問題就會拋出異常。但在阻塞模式中,遇到錯(cuò)誤并不會阻止操作。我們可以創(chuàng)建一個(gè)普通的TCP套接字,分別在阻塞模式和非阻塞模式中執(zhí)行操作實(shí)驗(yàn)。

為了能在阻塞模式中處理套接字,首先要創(chuàng)建一個(gè)套接字對象。然后,調(diào)用setblocking(1)把套接字設(shè)為阻塞模式,或者調(diào)用setblocking(0)把套接字設(shè)為非阻塞模式。最后,把套接字綁定到指定的端口上,監(jiān)聽進(jìn)入的連接。

代碼清單1-9展示了如何把套接字設(shè)為阻塞模式或非阻塞模式,如下所示:

#!/usr/bin/env python

# Python Network Programming Cookbook -- Chapter - 1

# This program is optimized for Python 2.7. It may run on any

# other Python version with/without modifications.

import socket

def test_socket_modes():

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

s.setblocking(1)

s.settimeout(0.5)

s.bind(("127.0.0.1", 0))

socket_address = s.getsockname()

print "Trivial Server launched on socket: %s" %str(socket_address)

while(1):

s.listen(1)

if __name__ == '__main__':

test_socket_modes()

運(yùn)行這個(gè)攻略后,會啟動一個(gè)簡易服務(wù)器,開啟阻塞模式,如下述命令所示:

$ python 1_9_socket_modes.py

Trivial Server launched on socket: ('127.0.0.1', 51410)

1.10.2原理分析

在這個(gè)攻略中,我們把1傳給setblocking()方法,啟用套接字的阻塞模式。類似地,可以把0傳給這個(gè)方法,把套接字設(shè)為非阻塞模式。

這個(gè)功能在后面的一些攻略中會用到,到時(shí)再詳細(xì)說明其真正作用。

1.11重用套接字地址

不管連接是被有意還是無意關(guān)閉,有時(shí)你想始終在同一個(gè)端口上運(yùn)行套接字服務(wù)器。某些情況下,如果客戶端程序需要一直連接指定的服務(wù)器端口,這么做就很有用,因?yàn)闊o需改變服務(wù)器端口。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的python网络编程项目_Python网络编程攻略的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。