python3網(wǎng)絡(luò)編程:socket的簡(jiǎn)單使用

01.套接字

套接字用于應(yīng)用程序間的通信智厌,任何程序間的通信開(kāi)始之前都要?jiǎng)?chuàng)建套接字
有兩種類(lèi)型的套接字:基于文件的和面向網(wǎng)絡(luò)的饭望。
套接字最初是為同一主機(jī)上的應(yīng)用程序所創(chuàng)建灭返,使得主機(jī)上運(yùn)行的一個(gè)進(jìn)程和另一個(gè)進(jìn)程進(jìn)行通信汤徽,也就是進(jìn)程間通信(IPC Inter Process Communication)打肝。
文件套接字:
Unix套接字是套接字的第一個(gè)家族脂新,家族名AF_UNIX(又名AF_LOCAL),家族名代表地址家族(address family)
網(wǎng)絡(luò)套接字:
網(wǎng)絡(luò)套接字也有自己的家族名粗梭,AF_INET戏羽,另一個(gè)地址家族AF_INET6是用于ipv6尋址。還有一些其他的地址家族楼吃,但是目前使用最廣泛的是AF_INET

python支持AF_UNIX.AF_NETLINK,AF_TIPC,AF_INET幾個(gè)家族始花。對(duì)于網(wǎng)絡(luò)編程來(lái)說(shuō),我們將使用AF_INET.所以接下來(lái)討論的內(nèi)容都是AF_INET家族的套接字
套接字地址有主機(jī)號(hào)(ip)和端口號(hào)兩個(gè)部分組成孩锡,有效端口號(hào)的范圍是0~65535酷宵,小于1024的端口號(hào)是系統(tǒng)預(yù)留的,所以我們寫(xiě)程序的時(shí)候不要去占用躬窜。

02.面向連接的套接字和無(wú)連接的套接字

001.面向連接的套接字

面向連接的通信提供序列化的浇垦、可靠的和不重復(fù)的數(shù)據(jù)交付,沒(méi)有記錄邊界荣挨。每條消息可以拆成多個(gè)片段男韧,并且每一個(gè)消息片段都能確保到達(dá)目的地朴摊,然后將他們按順序組合在一起,最后將完整消息傳遞給正在等待的應(yīng)用程序此虑。
主要就是傳輸控制協(xié)議tcp甚纲。
為了創(chuàng)建tcp套接字,必須使用SOCK_STREAM作為套接字類(lèi)型朦前。

002.無(wú)連接的套接字

不需要建立連接介杆,也無(wú)法確保數(shù)據(jù)的順序性,可靠性和重復(fù)性韭寸。
可以類(lèi)比于郵政服務(wù)春哨,信件和包裹也許并不能以發(fā)送順序到達(dá),也可能根本沒(méi)有到達(dá)恩伺。
相對(duì)于面向連接服務(wù)赴背,沒(méi)有創(chuàng)建維持連接需要的成本,資源消耗更小晶渠,更快速凰荚。
主要是用戶(hù)數(shù)據(jù)報(bào)協(xié)議UDP
為了創(chuàng)建UDP協(xié)議的套接字,必須使用SOCK_DGRAM作為套接字類(lèi)型乱陡。

tcp和udp都是結(jié)合ip協(xié)議尋找互聯(lián)網(wǎng)上的主機(jī)。所以這種系統(tǒng)被稱(chēng)為T(mén)CP/IP,UDP/IP

03.python 中的網(wǎng)絡(luò)編程

socket.socket(socket_family,socket_type,protocol=0)
socket_family是AF_UNIX或AF_INET仪壮,socket_type是SOCK_STREAM或SOCK_DGRAM憨颠。protocol通常省略,默認(rèn)為0.
socket對(duì)象的其他方法接下來(lái)將通過(guò)實(shí)例來(lái)演示:

下面首先演示的是一個(gè)tcp時(shí)間戳服務(wù)器:

import socket
import time
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)

# 創(chuàng)建服務(wù)端套接字用于接受客戶(hù)端的連接
tcpSerSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 綁定本地端口
tcpSerSock.bind(ADDR)
# 設(shè)定允許連接的最大數(shù)值
tcpSerSock.listen(5)

while True:
    print('waiting for connection,local address:',ADDR)
#     accept方法接受客戶(hù)端發(fā)送的請(qǐng)求积锅,并且產(chǎn)生一個(gè)服務(wù)客戶(hù)端用的socket爽彤,返回客戶(hù)端的地址
    tcpClientSock,addr = tcpSerSock.accept()
    print('...connected from:',addr)
    while True:
#         建立連接后,用tcpClientSock服務(wù)客戶(hù)端缚陷,接受客戶(hù)端發(fā)送的數(shù)據(jù)适篙,使用指定大小的緩沖區(qū)
        data = tcpClientSock.recv(BUFSIZE)
        print('recieving data:',data)
#     當(dāng)沒(méi)有收到數(shù)據(jù)時(shí)退出循環(huán)
        if not data:
            break
#         在客戶(hù)端發(fā)送的數(shù)據(jù)前加上時(shí)間戳再送回,socket需要放送bytes類(lèi)型的數(shù)據(jù),所以這里b是轉(zhuǎn)化二進(jìn)制數(shù)據(jù)
        tcpClientSock.send(b'[%s] %s'%(bytes(time.ctime(),'utf-8'),data))
#     關(guān)閉服務(wù)客戶(hù)端的socket
    tcpClientSock.close()
    
# 關(guān)閉服務(wù)器的socket,現(xiàn)實(shí)情況下服務(wù)器都是一直運(yùn)行的,所以一般不會(huì)關(guān)閉
tcpSerSock.close()




接下來(lái)是創(chuàng)建tcp客戶(hù)端
創(chuàng)建客戶(hù)端比服務(wù)器簡(jiǎn)單一些箫爷,
下面創(chuàng)建的客戶(hù)端連接之前創(chuàng)建的服務(wù)器嚷节,向服務(wù)器發(fā)送數(shù)據(jù),并且打印服務(wù)器返回的數(shù)據(jù)虎锚。


import socket
HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)

tcpCliSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcpCliSock.connect(ADDR)

while True:
    data = input('> ')
    if not data:
        break
#     socket需要放送bytes類(lèi)型的數(shù)據(jù)硫痰,所以這里encode是轉(zhuǎn)化二進(jìn)制數(shù)據(jù)
    tcpCliSock.send(data.encode('utf8'))
    data = tcpCliSock.recv(BUFSIZE)
    if not data:
        break
    print(data)
tcpCliSock.close()
          

接下來(lái)是創(chuàng)建udp服務(wù)器。由于是無(wú)連接的窜护,所以并沒(méi)有為了成功而使一個(gè)客戶(hù)端連接到一個(gè)獨(dú)立的套接字的“轉(zhuǎn)換”操作效斑。

import socket
import time

HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)

udpSerSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udpSerSock.bind(ADDR)

while True:
    print('waiting for message...')
    data,addr = udpSerSock.recvfrom(BUFSIZE)
    print('receiving data from %s,data:%s'%(addr,data))
    sendstr='[%s] %s'%(time.ctime(),data)
    udpSerSock.sendto(sendstr.encode('utf8'),addr)
    print('...received from and returned to:',addr)
                      
udpSerSock.close()
# 創(chuàng)建udp客戶(hù)端
import socket
import time

HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)

udpCliSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

while True:
    data = input('>')
    if not data:
        break
    udpCliSock.sendto(data.encode('utf8'),ADDR)
    data,addr = udpCliSock.recvfrom(BUFSIZE)
    if not data:
        break
    print(data)
                    
udpCliSock.close()

04.socketserver模塊

socketserver是python標(biāo)準(zhǔn)庫(kù)里面的一個(gè)高級(jí)模塊,目標(biāo)是簡(jiǎn)化創(chuàng)建客戶(hù)端和服務(wù)器的代碼柱徙。

下面我們先介紹tcp時(shí)間戳服務(wù)器的例子:

import socketserver
import time

HOST = ''
PORT = 21567
ADDR = (HOST,PORT)


class MyRequestHandler(socketserver.StreamRequestHandler):
    def handle(self):
        print('...connected from:',self.client_address)
        self.wfile.write(('[%s] %s'%(time.ctime(),self.rfile.readline())).encode('utf8'))


tcpServ = socketserver.TCPServer(ADDR,MyRequestHandler)
print('waiting for connection...')
tcpServ.serve_forever()

客戶(hù)端

import socket
HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024 
ADDR = (HOST,PORT)

while True:
    tcpCliSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    tcpCliSock.connect(ADDR)
    data = input('> ')
    if not data:
        break
    tcpCliSock.send(('%s\r\n'%data).encode('utf8'))
    data = tcpCliSock.recv(BUFSIZE)
    if not data:
        break
    print(data.strip())
    tcpCliSock.close()

用這個(gè)高級(jí)模塊缓屠,自己帶一些異常處理奇昙,可以檢測(cè)到鍵盤(pán)中斷了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末敌完,一起剝皮案震驚了整個(gè)濱河市储耐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蠢挡,老刑警劉巖弧岳,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異业踏,居然都是意外死亡禽炬,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)勤家,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)腹尖,“玉大人,你說(shuō)我怎么就攤上這事伐脖∪柔#” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵讼庇,是天一觀(guān)的道長(zhǎng)绎巨。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蠕啄,這世上最難降的妖魔是什么场勤? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮歼跟,結(jié)果婚禮上和媳,老公的妹妹穿的比我還像新娘。我一直安慰自己哈街,他們只是感情好留瞳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著骚秦,像睡著了一般她倘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上作箍,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天帝牡,我揣著相機(jī)與錄音,去河邊找鬼蒙揣。 笑死靶溜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播罩息,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嗤详,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了瓷炮?” 一聲冷哼從身側(cè)響起葱色,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎娘香,沒(méi)想到半個(gè)月后苍狰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烘绽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年淋昭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片安接。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡翔忽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盏檐,到底是詐尸還是另有隱情歇式,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布胡野,位于F島的核電站材失,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏硫豆。R本人自食惡果不足惜龙巨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望够庙。 院中可真熱鬧恭应,春花似錦抄邀、人聲如沸耘眨。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)剔难。三九已至,卻和暖如春奥喻,著一層夾襖步出監(jiān)牢的瞬間偶宫,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工环鲤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纯趋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吵冒,于是被迫代替她去往敵國(guó)和親纯命。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容