什么是sockets
Socket又稱"套接字"此衅,應(yīng)用程序通常通過"套接字"向網(wǎng)絡(luò)發(fā)出請(qǐng)求或者應(yīng)答網(wǎng)絡(luò)請(qǐng)求金句,使主機(jī)間或者一臺(tái)計(jì)算機(jī)上的進(jìn)程間可以通訊泪勒。
socket起源于UNIX栅组,在Unix一切皆文件哲學(xué)的思想下,socket是一種"打開—讀/寫—關(guān)閉"模式的實(shí)現(xiàn)梅掠,服務(wù)器和客戶端各自維護(hù)一個(gè)"文件"酌住,在建立連接打開后店归,可以向自己文件寫入內(nèi)容供對(duì)方讀取或者讀取對(duì)方內(nèi)容,通訊結(jié)束時(shí)關(guān)閉文件酪我。
socket的英文原義是“插槽”或“插座”消痛,就像我們家里座機(jī)一樣,如果沒有網(wǎng)線的那個(gè)插口都哭,電話是無法通信的肄满。Socket是實(shí)現(xiàn)TCP,UDP協(xié)議的接口质涛,便于使用TCP,UDP。
基本上掰担,Socket 是任何一種計(jì)算機(jī)網(wǎng)絡(luò)通訊中最基礎(chǔ)的內(nèi)容汇陆。例如當(dāng)你在瀏覽器地址欄中輸入 http://www.cnblogs.com/ 時(shí),你會(huì)打開一個(gè)套接字带饱,然后連接到 http://www.cnblogs.com/ 并讀取響應(yīng)的頁面然后然后顯示出來毡代。而其他一些聊天客戶端如 gtalk 和 skype 也是類似。任何網(wǎng)絡(luò)通訊都是通過 Socket 來完成的勺疼。
Python 官方關(guān)于 Socket 的函數(shù)請(qǐng)看http://docs.python.org/library/socket.html
socket和file的區(qū)別:
1教寂、file模塊是針對(duì)某個(gè)指定文件進(jìn)行【打開】【讀寫】【關(guān)閉】
2、socket模塊是針對(duì) 服務(wù)器端 和 客戶端Socket 進(jìn)行【打開】【讀寫】【關(guān)閉】
運(yùn)行過程
首先啟動(dòng)服務(wù)端执庐,監(jiān)聽請(qǐng)求酪耕;
然后通過客戶端去發(fā)出請(qǐng)求;
接下來觀察輸出轨淌;
運(yùn)行流程圖
常用函數(shù)
服務(wù)器端
- s.bind()
綁定地址(host,port)到套接字迂烁, 在AF_INET下,以元組(host,port)的形式表示地址。 - s.listen()
開始TCP監(jiān)聽递鹉。backlog指定在拒絕連接之前盟步,操作系統(tǒng)可以掛起的最大連接數(shù)量。該值至少為1躏结,大部分應(yīng)用程序設(shè)為5就可以了却盘。 - s.accept()
被動(dòng)接受TCP客戶端連接,(阻塞式)等待連接的到來
客戶端
- s.connect()
主動(dòng)初始化TCP服務(wù)器連接,媳拴。一般address的格式為元組(hostname,port)黄橘,如果連接出錯(cuò),返回socket.error錯(cuò)誤禀挫。 - s.connect_ex()
connect()函數(shù)的擴(kuò)展版本,出錯(cuò)時(shí)返回出錯(cuò)碼,而不是拋出異常
公共用途的函數(shù)
s.recv()
接收TCP數(shù)據(jù)旬陡,數(shù)據(jù)以字符串形式返回,bufsize指定要接收的最大數(shù)據(jù)量语婴。flag提供有關(guān)消息的其他信息描孟,通呈荒溃可以忽略。s.send()
發(fā)送TCP數(shù)據(jù)匿醒,將string中的數(shù)據(jù)發(fā)送到連接的套接字场航。返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于string的字節(jié)大小廉羔。s.sendall()
完整發(fā)送TCP數(shù)據(jù)溉痢,完整發(fā)送TCP數(shù)據(jù)。將string中的數(shù)據(jù)發(fā)送到連接的套接字憋他,但在返回之前會(huì)嘗試發(fā)送所有數(shù)據(jù)孩饼。成功返回None,失敗則拋出異常竹挡。s.close()
關(guān)閉套接字s.recvform()
接收UDP數(shù)據(jù)镀娶,與recv()類似,但返回值是(data,address)揪罕。其中data是包含接收數(shù)據(jù)的字符串梯码,address是發(fā)送數(shù)據(jù)的套接字地址。s.sendto()
發(fā)送UDP數(shù)據(jù)好啰,將數(shù)據(jù)發(fā)送到套接字轩娶,address是形式為(ipaddr,port)的元組框往,指定遠(yuǎn)程地址鳄抒。返回值是發(fā)送的字節(jié)數(shù)。s.getpeername()
返回連接套接字的遠(yuǎn)程地址搅窿。返回值通常是元組(ipaddr,port)嘁酿。s.getsockname()
返回套接字自己的地址。通常是一個(gè)元組(ipaddr,port)s.setsockopt(level,optname,value)
設(shè)置給定套接字選項(xiàng)的值男应。s.getsockopt(level,optname[.buflen])
返回套接字選項(xiàng)的值闹司。s.settimeout(timeout)
設(shè)置套接字操作的超時(shí)期,timeout是一個(gè)浮點(diǎn)數(shù)沐飘,單位是秒游桩。值為None表示沒有超時(shí)期。一般耐朴,超時(shí)期應(yīng)該在剛創(chuàng)建套接字時(shí)設(shè)置借卧,因?yàn)樗鼈兛赡苡糜谶B接的操作(如connect())s.gettimeout()
返回當(dāng)前超時(shí)期的值,單位是秒筛峭,如果沒有設(shè)置超時(shí)期铐刘,則返回None。s.fileno()
返回套接字的文件描述符影晓。s.setblocking(flag)
如果flag為0镰吵,則將套接字設(shè)為非阻塞模式檩禾,否則將套接字設(shè)為阻塞模式(默認(rèn)值)。非阻塞模式下疤祭,如果調(diào)用recv()沒有發(fā)現(xiàn)任何數(shù)據(jù)盼产,或send()調(diào)用無法立即發(fā)送數(shù)據(jù),那么將引起socket.error異常勺馆。s.makefile()
創(chuàng)建一個(gè)與該套接字相關(guān)連的文件
服務(wù)器端代碼SocketServer.py
import socket
s = socket.socket()
host = '0.0.0.0'
port = 9630
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print('Received message == {0}'.format(c.recv(1024).decode('utf-8')))
c.send(b'this come from server')
c.close()
客戶端源代碼SocketClient.py:
import socket
c = socket.socket()
host = '192.168.1.1'
port = 9630
c.connect((host, port))
print('已連接 {0}'.format(host))
c.sendall(b"this come from client")
print(c.recv(1024).decode('utf-8'))
自己的理解
- 對(duì)于信息的傳遞戏售,如果之前的send消息沒被對(duì)端recv,那么這一次的send會(huì)尾接上次信息草穆,直到recv才會(huì)清空消息隊(duì)列灌灾。
- 在服務(wù)器端執(zhí)行了close后,之后客戶端再次send時(shí)悲柱,服務(wù)端不會(huì)處理
- 一次連接只能接受一次sendall
參考文章
http://www.cnblogs.com/idontknowthisperson/p/5958536.html
http://www.cnblogs.com/aylin/p/5572104.html