socket模塊中用于創(chuàng)建套接字的函數(shù)是socket(),語法是
socket(socket_family,socket_type,protocol=0)
socket_family可以是AF_UNIX或是AF_INET,socket_type可以是SOCK_STREAM或是SOCK_DGRAM,protocol一般情況下是不填的,默認(rèn)為 0.
創(chuàng)建TCP/IP套接字 tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
創(chuàng)建UDP/IP套接字 udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
通過調(diào)用socket.socket()創(chuàng)建一個(gè)套接字對(duì)象,之后的交互都可以通過調(diào)用這個(gè)套接字對(duì)象的方法來進(jìn)行。
現(xiàn)在列一些套接字對(duì)象常用的方法
服務(wù)器端套接字方法
s.bind() 綁定地址到套接字對(duì)象,地址為主機(jī)、端口對(duì)
s.listen() 監(jiān)聽端口
s.accept() 被動(dòng)的阻塞式的接受連接
客戶端套接字方法
s.connect() 初始化連接
s.connect_ex() connect()的擴(kuò)展版本,出錯(cuò)時(shí)會(huì)返回錯(cuò)誤碼而不是拋出異常
共用套接字方法
s.recv() 接收TCP數(shù)據(jù)
s.send() 發(fā)送TCP數(shù)據(jù)
s.sendall() 完整發(fā)送TCP數(shù)據(jù)
s.recvfrom() 接收UDP數(shù)據(jù)
s.sendto() 發(fā)送UDP數(shù)據(jù)
s.getpeername() 連接到當(dāng)前套接字的遠(yuǎn)端的地址
s.getsockname() 當(dāng)前套接字的地址
s.getsockopt() 返回指定套接字的參數(shù)
s.setsockopt() 設(shè)置指定套接字的參數(shù)
s.close() 關(guān)閉套接字
阻塞式套接字方法
s.setblocking() 設(shè)置套接字的阻塞與非阻塞模式
s.settimeout() 設(shè)置阻塞套接字操作的超時(shí)時(shí)間
s.gettimeout() 得到阻塞套接字操作的超時(shí)時(shí)間
面向文件的套接字的方法
s.fileno() 套接字的文件描述符
s.makefile() 創(chuàng)建一個(gè)與該套接字關(guān)聯(lián)的文件
創(chuàng)建TCP服務(wù)器
先給出偽代碼,來理解服務(wù)器創(chuàng)建的過程。
s = socket() #創(chuàng)建服務(wù)器套接字
s.bind() #把地址綁定到套接字上
s.listen() #監(jiān)聽連接
inf_loop: #服務(wù)器無限循環(huán)
c=s.accept()#接受客戶的連接,accept()函數(shù)會(huì)返回一個(gè)連接對(duì)象和連接地址元祖
comm_loop:#通訊循環(huán)
c.recv()/c.send()#收發(fā)數(shù)據(jù)
c.close()#關(guān)閉客戶連接
s.close()#關(guān)閉服務(wù)器連接
服務(wù)器在一個(gè)端口接受請(qǐng)求,一旦接受到連接,accept()函數(shù)就會(huì)返回一個(gè)單獨(dú)的客戶的套接字對(duì)象用戶后續(xù)的通信。這樣,接受到一個(gè)連接后便使用其他的端口通信而不妨礙服務(wù)的監(jiān)聽。通常,服務(wù)器使用多線程技術(shù)來處理。使用accept()函數(shù)返回的套接字對(duì)象來創(chuàng)建一個(gè)線程專門處理客戶連接。主端口就能空出來接受其他的客戶端請(qǐng)求了。
下面的示例來自《Python核心編程第二版》
TCP服務(wù)器示例
TCP時(shí)間戳服務(wù)器tsTserv.py
#!/usr/bin/env python
from socket import * #為了防止名字空間重復(fù),盡量不要這么導(dǎo)入模塊
from time import ctime
HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket(AF_INET,SOCK_STREAM) #TCP/IP套接字
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
while True:
print 'Waiting for connection...'
tcpCliSock,addr = tcpSerSock.accept()
print 'connected from:',addr
while True:
date = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send('[%s]%s' %(ctime(),data))
tcpCliSock.close()
tcpSerSock.close()
程序就不解釋了,,很明了了已經(jīng)。。。
下面是客戶端的偽代碼
cs = socket() #創(chuàng)建客戶端套接字
cs.connect() #連接到服務(wù)器
comm_loop: #通信循環(huán)
cs.send()/cs.recv() # 對(duì)話(發(fā)送/接收) cs.close() # 關(guān)閉客戶套接字 客戶端的實(shí)現(xiàn)
#!/usr/bin/env python
from socket import *
HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT) tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR) while True:
data = raw_input('> ')
if not data:
break
tcpCliSock.send(data)
data = tcpCliSock.recv(BUFSIZ)
if not data:
break print data
tcpCliSock.close() 客戶端的功能很簡(jiǎn)單,獲得用戶輸入發(fā)送到時(shí)間戳服務(wù)器,接收服務(wù)器加上時(shí)間戳的數(shù)據(jù)并顯示出來
如果服務(wù)器端沒有運(yùn)行,執(zhí)行客戶端會(huì)拋出異常,同樣,結(jié)束服務(wù)器端的循環(huán)也會(huì)拋出異常,為了優(yōu)雅的退出,友好的錯(cuò)誤輸出,可以將必要的程序比如服務(wù)器的循環(huán)放在try-except語句的try子句當(dāng)中,在異常處理子句中調(diào)用close()來關(guān)閉套接字。
關(guān)于TCP/IP套接字也就介紹這么些內(nèi)容,各個(gè)流程按偽代碼給出的進(jìn)行操作。
UDP連接是無連接的,在處理上會(huì)與TCP套接字有所不同。具體該怎么實(shí)現(xiàn),就等下一次吧。。。
Socket
低層網(wǎng)絡(luò)接口(每個(gè) BSD API) SocketServer 提供簡(jiǎn)化網(wǎng)絡(luò)服務(wù)器開發(fā)的類 讓我們來看一下這些模塊,以便理解它們是如何工作的。 socket 模塊 Socket 模塊提供了 UNIX 程序員所熟悉的基本網(wǎng)絡(luò)服務(wù)(也稱為 BSD API)。這個(gè)模塊中提供了在構(gòu)建 socket 服務(wù)器和客戶機(jī)時(shí)所需要的所有功能。 這個(gè) API 與標(biāo)準(zhǔn)的 C API 之間的區(qū)別在于它是面向?qū)ο蟮?。在C中,socket描述符是從socket調(diào)用中獲得的,然后會(huì)作為一個(gè)參數(shù)傳遞給BSD API函數(shù)。在Python中,socket 方法會(huì)向應(yīng)用socket方法的對(duì)象返回一個(gè)socket對(duì)象。表2給出了幾個(gè)類方法,表3顯示了一部分實(shí)例方法。 表2. Socket 模塊的類方法 類方法 說明 Socket 低層網(wǎng)絡(luò)接口(每個(gè) BSD API) socket.socket(family, type) 創(chuàng)建并返回一個(gè)新的 socket 對(duì)象 socket.getfqdn(name) 將使用點(diǎn)號(hào)分隔的 IP 地址字符串轉(zhuǎn)換成一個(gè)完整的域名 socket.gethostbyname(hostname) 將主機(jī)名解析為一個(gè)使用點(diǎn)號(hào)分隔的 IP 地址字符串 socket.fromfd(fd, family, type) 從現(xiàn)有的文件描述符創(chuàng)建一個(gè) socket 對(duì)象 表3. Socket 模塊的實(shí)例方法 實(shí)例方法 說明 sock.bind( (adrs, port) ) 將 socket 綁定到一個(gè)地址和端口上 sock.accept() 返回一個(gè)客戶機(jī) socket(帶有客戶機(jī)端的地址信息) sock.listen(backlog) 將 socket 設(shè)置成監(jiān)聽模式,能夠監(jiān)聽 backlog 外來的連接請(qǐng)求 sock.connect( (adrs, port) ) 將 socket 連接到定義的主機(jī)和端口上 sock.recv( buflen[, flags] ) 從 socket 中接收數(shù)據(jù),最多 buflen 個(gè)字符 sock.recvfrom( buflen[, flags] ) 從 socket 中接收數(shù)據(jù),最多 buflen 個(gè)字符,同時(shí)返回?cái)?shù)據(jù)來源的遠(yuǎn)程主機(jī)和端口號(hào) sock.send( data[, flags] ) 通過 socket 發(fā)送數(shù)據(jù) sock.sendto( data[, flags], addr ) 通過 socket 發(fā)送數(shù)據(jù) sock.close() 關(guān)閉 socket sock.getsockopt( lvl, optname ) 獲得指定 socket 選項(xiàng)的值 sock.setsockopt( lvl, optname, val ) 設(shè)置指定 socket 選項(xiàng)的值 類方法和實(shí)例方法之間的區(qū)別在于,實(shí)例方法需要有一個(gè)socket實(shí)例(從socket返回)才能執(zhí)行,而類方法則不需要。 SocketServer 模塊 SocketServer 模塊是一個(gè)十分有用的模塊,它可以簡(jiǎn)化socket服務(wù)器的開發(fā)。有關(guān)這個(gè)模塊的使用的討論已經(jīng)遠(yuǎn)遠(yuǎn)超出了本教程的范圍,但是我將展示一下它的基本用法,然后您可以參閱參考資料一節(jié)中給出的鏈接。 考慮清單 2 中給出的例子。此處,我們實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的 “Hello World” 服務(wù)器,當(dāng)客戶機(jī)連接它時(shí),它就會(huì)顯示這樣一條消息。我首先創(chuàng)建一個(gè)請(qǐng)求處理程序,它繼承了 SocketServer . StreamRequestHandler 類。我們定義了一個(gè)名為 handle 的方法,它處理服務(wù)器的請(qǐng)求。服務(wù)器所做的每件事情都必須在這個(gè)函數(shù)的上下文中進(jìn)行處理(最后,關(guān)閉這個(gè) socket)。這個(gè)過程的工作方式非常簡(jiǎn)單,但是您可以使用這個(gè)類來實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 HTTP 服務(wù)器。在 handle 方法中,我們打一個(gè)招呼就退出了。 現(xiàn)在連接處理程序已經(jīng)準(zhǔn)備就緒了,剩下的工作是創(chuàng)建 socket 服務(wù)器。我們使用了 SocketServer .TCPServer 類,并提供了地址和端口號(hào)(要將服務(wù)器綁定到哪個(gè)端口上)以及請(qǐng)求處理方法。結(jié)果是一個(gè) TCPServer 對(duì)象。調(diào)用 serve_forever 方法啟動(dòng)服務(wù)器,并使其對(duì)這個(gè)連接可用。 清單 2. 用 SocketServer 模塊實(shí)現(xiàn)一個(gè)簡(jiǎn)單的服務(wù)器 Toggle line numbers Toggle line numbers 1 import SocketServer 2 3 class hwRequestHandler( SocketServer.StreamRequestHandler ): 4 def handle( self ): 5 self.wfile.write("Hello World!/n") 6 7 8 server = SocketServer.TCPServer( ("", 2525), hwRequestHandler ) 9 server.serve_forever() 就是這樣!Python 允許這種機(jī)制的任何變種,包括 UDPServers 以及派生進(jìn)程和線程的服務(wù)器。請(qǐng)參閱 參考資料一節(jié)中更多信息的鏈接。 本文來自,如果查看原文請(qǐng)點(diǎn):http://blog./u2/60332/showart_2127355.html |
|