什么是socket
網絡上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個socket。socket通常也稱作"套接字",用於描述IP地址和端口,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。在Internet上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個端口上,不同的端口對應於不同的服務。
Socket的英文原義是“孔”或“插座”。Socket正如其英文原意那樣,像一個多孔插座。一台主機猶如布滿各種插座的房間,每個插座有一個編號,有的插座提供220伏交流電, 有的提供110伏交流電,有的則提供有線電視節目。 客戶軟件將插頭插到不同編號的插座,就可以得到不同的服務。
我知道上面那段話很枯燥,那就忘記吧!我們只需要記得:兩個程序通過“網絡”交互數據就使用socket,它只負責兩件事:建立連接,傳遞數據。不能再簡練了!!!
如何執行一段socket代碼?
首先,我們先看下面這個例子,什么都不需要懂,我們只知道這么寫就可以實現一個socket,讓兩個程序互相傳遞消息:
server:
client:
先說一下它們是怎么跑起來的,新建兩個python文件:socket_server.py,socket_client.py 分別將demo1_server Code和demo1_client Code中的代碼粘到對應的文件中,先執行socket_server.py,再執行socket_client.py,就可以看到效果啦!代碼拿去,先體驗一下socket的效果。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 __author__ = 'Eva_J' 4 import socket 5 6 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 7 sock.bind(('127.0.0.1',8001)) 8 sock.listen(5) 9 10 while True: 11 print 'waiting....' 12 connection, address = sock.accept() 13 receive = connection.recv(1024) 14 print 'receive the message from client:',receive 15 connection.send("received") 16 connection.close()
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 __author__ = 'Eva_J' 4 import socket 5 6 obj_client = socket.socket() 7 obj_client.connect(('127.0.0.1',8001)) 8 obj_client.send('help') 9 server_data = obj_client.recv(1024) 10 print server_data 11 obj_client.close()
一分鍾擁有一個自己的socket程序!
執行成功了么?我們先不解釋原理,一切以能把socket用起來為前提,把上面這段代碼當做實現socket的模板代碼,來看看哪些東西是我們可以替換的,先拼湊一個屬於自己的socket程序。
server:
client:
![]()
我們先從打印出來的內容來看,server端接收到了從client端發送過來的信息 'help' 。並且給client端發送了一條確認信息 'received',我們在client端接收到了這條信息。這就是數據交互的過程。send是發消息方法,recv是接收消息方法。我們只需要修改send和recv中的內容,就可以實現兩個程序的數據交互了。
socket的實現就像是快遞員取快遞的過程,寄出包裹的是server端,快遞員是client端,send和recv中的內容就是我們要寄出的東西,那么准備好了要寄出的東西,我們要告訴快遞員到哪里來取件,看server中的sock.bind方法,這里面傳了一個元組('ip','port')給bind方法,就是把包裹放在這個地址的這個端口等待快遞員;而client端的obj_client.connect方法是告訴快遞員,去那個地址找這個端口去取包裹。所以這個元組中的ip和port內容必須一致,是我和快遞員約好的。我send的內容無所謂是什么,我send什么,客戶端就recv什么,因為我要寄什么,快遞員拿到的就是什么,他沒有權利左右我寄什么東西。現在就行動起來,把要寄的東西和放東西的地址換成你自己的,來get一個屬於自己的socket程序吧。
socket程序代碼詳解:
server:
client: 
創建socket對象——參數詳解:

參數一:地址簇
socket.AF_INET IPv4(默認)
socket.AF_INET6 IPv6
socket.AF_UNIX 只能夠用於單一的Unix系統進程間通信
參數二:類型
socket.SOCK_STREAM 流式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 可靠的連續數據包服務
參數三:協議(這個參數用默認的就好,所以在我們創建對象的時候沒有使用此參數,忘記這個參數吧)
0 (默認)與特定的地址家族相關的協議,如果是 0 ,則系統就會根據地址格式和套接類別,自動選擇一個合適的協議'
UDP協議實現socket代碼實例:
我們剛剛看的例子中都是使用TCP協議進行傳輸,下面上一段UDP的例子。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import socket 4 ip_port = ('127.0.0.1',9999) 5 6 sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) 7 while True: 8 inp = raw_input('數據:').strip() 9 if inp == 'exit': 10 break 11 sk.sendto(inp,ip_port) 12 sk.close()
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = ('127.0.0.1',9999) sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) sk.bind(ip_port) while True: data = sk.recv(1024) print data
參考:
socket詳解:http://www.cnblogs.com/wupeiqi/articles/5040823.html
TCP和UDP協議的區別:http://jingyan.baidu.com/article/6dad5075df3452a123e36ecb.html
