【Python】socket 程式設計初探

楊奇龍發表於2016-03-28
一 簡介
  socket是兩個應用程式進行通訊的管道,這兩個應用程式可以在同一臺機器上,也可以位於兩臺不同的機器上,相同的網路或者不同網路之間的。Python  socket有豐富的類和方法,可以簡化socket程式設計。本文算是一個學習筆記。
二  socket 
2.1 socket型別

socket.AF_UNIX 

只能夠用於單一的Unix系統程式間通訊

socket.AF_INET 

伺服器之間網路通訊

socket.AF_INET6 

用於IPv6網路的通訊

socket.SOCK_STREAM

流式socket , for TCP

socket.SOCK_DGRAM 

資料包式socket , for UDP

socket.SOCK_RAW

原始套接字,普通的套接字無法處理ICMPIGMP等網路報文,而SOCK_RAW可以;其次,SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始套接字,可以通過IP_HDRINCL套接字選項由使用者構造IP頭。

socket.SOCK_SEQPACKET 

可靠的連續資料包服務


例子
建立TCP Socket:
import socket
tcpSerSock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
建立UDP Socket:
tcpSerSock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
注意點:
1)TCP傳送資料時,已建立好TCP連線,所以不需要指定地址。UDP是面向無連線的,每次傳送要指定是發給誰。
2)服務端與客戶端不能直接傳送列表,元組,字典。需要字串化repr(data)。

2.2 socket函式 
服務端socket函式

socket.bind(address)   

將套接字繫結到地址, AF_INET,以元組(host,port)的形式表示地址.

socket.listen(backlog)

開始監聽TCP傳入連線。backlog指定在拒絕連線之前,作業系統可以掛起的最大連線數量。該值至少為1

socket.accept()

接受TCP連線並返回(conn,address,其中conn是新的套接字物件,可以用來接收和傳送資料。address是連線客戶端的地址。


客戶端socket函式

socket.connect(address) 

連線到address處的套接字。一般address的格式為元組(hostname,port),如果連線出錯,返回socket.error錯誤。

socket.connect_ex(adddress)

功能與connect(address)相同,但是成功返回0,失敗返回errno的值。


公用函式

socket.recv(bufsize[,flag])

接受TCP套接字的資料。資料以字串形式返回,bufsize指定要接收的最大資料量。flag提供有關訊息的其他資訊,通常可以忽略。

socket.send(string[,flag]) 

傳送TCP資料。將string中的資料傳送到連線的套接字。返回值是要傳送的位元組數量,該數量可能小於string的位元組大小。

socket.sendall(string[,flag])

完整傳送TCP資料。將string中的資料傳送到連線的套接字,但在返回之前會嘗試傳送所有資料。成功返回None,失敗則丟擲異常。

socket.recvfrom(bufsize[.flag])

接受UDP套接字的資料。與recv()類似,但返回值是(data,address)。其中data是包含接收資料的字串,address是傳送資料的套接字地址。

socket.sendto(string[,flag],address)

傳送UDP資料。將資料傳送到套接字,address是形式為(ipaddrport)的元組,指定遠端地址。返回值是傳送的位元組數。

socket.close()

關閉套接字。

socket.getpeername()

返回連線套接字的遠端地址。返回值通常是元組(ipaddr,port)。

socket.getsockname()

返回套接字自己的地址。通常是一個元組(ipaddr,port)

socket.setsockopt(level,optname,value)

設定給定套接字選項的值。

socket.getsockopt(level,optname[.buflen])

返回套接字選項的值。

socket.settimeout(timeout)

設定套接字操作的超時期,timeout是一個浮點數,單位是秒。值為None表示沒有超時期。一般,超時期應該在剛建立套接字時設定,因為它們可能用於連線的操作(如connect()

socket.fileno()

返回套接字的檔案描述符。

socket.setblocking(flag)

如果flag0,則將套接字設為非阻塞模式,否則將套接字設為阻塞模式(預設值)。非阻塞模式下,如果呼叫recv

socket.makefile()

建立一個與該套接字相關連的檔案


三 建立socket連線
服務端
1 建立socket物件。
  tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2 使用bind方法來將socket繫結到指定地址和埠。
  tcpSock.bind(address,port)
3 使用listen方法接收連線請求。
  tcpSock.listen( backlog )
  backlog指定最多允許多少個客戶連線到伺服器。它的值至少為1。收到連線請求後,這些請求需要排隊,如果佇列滿,就拒絕請求。
4 通過socket的accept方法等待客戶請求連線。
  connection, address = socket.accept()
  呼叫accept方法時,socket會時入"waiting"狀態,等待客戶請求連線,當客戶端傳送請求到服務端時,accept方法建立連線並返回伺服器。accept方法返回一個含有兩個元素的 元組(connection,address)。
  第一個元素 connection是新的socket物件,伺服器必須通過它與客戶通訊;
  第二個元素 address是客戶的IP地址。
5 處理階段,伺服器和客戶端通過send和recv方法通訊(傳輸資料)。伺服器呼叫send方法以字串形式向客戶傳送資料,也可以使用recv方法從客戶接收資訊。呼叫recv時,
伺服器必須設定接收的最大資料量。recv方法在接收資料時會進入“blocked”狀態,最後返回一個字串,用它表示收到的資料。
如果傳送的資料量超過recv所允許接收的限制,資料會被截斷。多餘的資料將緩衝於接收端。下一次呼叫recv時,多餘的資料會從緩衝區刪除(以及自上次呼叫recv以來,客戶可能傳送的其它任何資料)
6 傳輸結束,伺服器呼叫socket的close方法關閉連線。
客戶端
1 建立一個socket以連線伺服器,和伺服器端建立socket物件一樣。
  tcpCliSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
2 使用socket的connect方法連線伺服器。
  tcpCliSock.connect( (host,port) )
  host代表伺服器主機名或IP,port代表伺服器程式所繫結的埠號。如連線成功,客戶就可通過套接字與伺服器通訊,如果連線失敗,會引發socket.error異常。
3 處理階段,客戶和伺服器將通過send方法和recv方法通訊。
  tcpCliSock.send(data) 
4 傳輸結束,客戶通過呼叫socket的close方法關閉連線。
  tcpCliSock.close()
一圖勝千言 ,socket 建立連線的過程 via 


圖片來自於 《socket 套接字
四 talk is cheap ,show me the code .
程式碼實現了一個client 端通過socket 向 server端傳送資訊的程式,
server.py
  1. #coding:utf8
  2. import socket
  3. from time import ctime
  4. HOST=''
  5. PORT=9999
  6. BUFSIZE=1024
  7. ADDR=(HOST,PORT)
  8. tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  9. tcpSock.bind(ADDR)
  10. tcpSock.listen(5)
  11. while True:
  12.     print 'waiting for connection ....'
  13.     tcpCliSock,addr = tcpSock.accept()
  14.     print '...connected from ',addr
  15.     while True:
  16.         data = tcpCliSock.recv(BUFSIZE)
  17.         if not data:
  18.             break
  19.         elif data == 'exit':
  20.             tcpCliSock.send('see you agine')
  21.             tcpCliSock.close()
  22.             exit(0)
  23.         tcpCliSock.send('%s, %s ' %(ctime(),data))
  24.         print [ctime()],':',data
  25. tcpCliSock.close()
  26. tcpSock.close()
  27. exit(0)
client.py 
  1. #coding:utf8
  2. import socket
  3. HOST= '10.0.2.6' #server 主機ip
  4. PORT=9999
  5. BUFSIZE=1024
  6. ADDR=(HOST,PORT)
  7. tcpCliSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  8. tcpCliSock.connect(ADDR)
  9. while True:
  10.     try:
  11.         data = raw_input('>')
  12.         if not data :
  13.             break
  14.         tcpCliSock.send(data)
  15.         data = tcpCliSock.recv(BUFSIZE)
  16.         if not data:
  17.             break
  18.         print '%s say: %s' %(HOST,data)
  19.         if data == 'see you agine':
  20.             exit(0)
  21.     except (KeyboardInterrupt, SystemExit):
  22.         tcpCliSock.close()
  23.         exit(0)





五 推薦閱讀
 1 python  socket 官方文件 
 2 《socket 網路程式設計》
 3 《Linux socket 程式設計》

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22664653/viewspace-2065183/,如需轉載,請註明出處,否則將追究法律責任。

相關文章