python之socket編程


  • 實例一:最簡單的socket例子
    這個程序矮锈,實現(xiàn)了客戶端向服務端發(fā)送數(shù)據(jù)铐伴,服務端將小寫字母變?yōu)榇髮懖⑶曳祷?/strong>
服務端
import socket
server=socket.socket()              #默認ipv4 tcp/ip 相當于聲明socket類型同時生成socket連接對象  既定義了地址簇,又定義了協(xié)議類型
server.bind(('localhost',1010) )        #綁定要監(jiān)聽的端口,只接受一個參數(shù)曼月,是一個元組

server.listen()                         #開始監(jiān)聽
print('我要開始等電話了!')             #但是這個地方還沒有真正開始等衙猪,只是做好了準備工作



conn,addr=server.accept()               #等電話打進來馍乙,真正的開始等電話打進來
print(conn,addr)                        #conn就是客戶端連過來而在服務器端為其生成的一個連接實例,也就是標記垫释,后面就是對方的地址
print("電話來了丝格!")
data=conn.recv(1024)                    #使用實例接受,發(fā)送
print(data)
conn.send(data.upper())                 #發(fā)過去變成大寫
server.close()                          #關(guān)閉手機 所以是server



# server.accept()
# data=server.recv(1024)
# print('recv ',data)
# server.send(data.upper())
# server.close()
#TypeError: a bytes-like object is required, not 'str'
#不能直接使用server去接聽 server.accept
#這里就需要想手機切換通話棵譬,只是一根電話線显蝌,讓別的人通過這一根電話線打進來切換接聽另一個人
#所以用該給每個人標記一下  conn,addr=server.accept()    返回第一個是連接的標記位,第二個是對方的地址


結(jié)果:
F:\anaconda\python.exe F:/web/s14/網(wǎng)絡編程订咸、socket編程/socket_server.py
我要開始等電話了曼尊!
<socket.socket fd=272, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 1010), raddr=('127.0.0.1', 49866)> ('127.0.0.1', 49866)
電話來了!
b'hello world!'
客戶端

import socket
client=socket.socket()                           #默認ipv4 tcp/ip 相當于聲明socket類型同時生成socket連接對象
client.connect(('localhost',1010))
client.send(b"hello world!")         #  不加b會出現(xiàn)這個錯誤   : TypeError: a bytes-like object is required, not 'str'   在python2里面可以發(fā)字符串脏嚷、字節(jié)bytes
#但是在python里只能發(fā)比特流的bytes類型
data=client.recv(1024)                           #收1024字節(jié)的數(shù)據(jù)   1kb
print(data)
client.close()

結(jié)果:

F:\anaconda\python.exe F:/web/s14/網(wǎng)絡編程骆撇、socket編程/socket_client.py
b'HELLO WORLD!'

  • 實例二:實現(xiàn)服務器和客戶端重復發(fā)送和接受多次
客戶端
import socket
client=socket.socket()
client.connect(('localhost',1010))
while True:
    msg=input('>>:').strip()
    if len(msg) == 0:continue
    client.send(msg.encode("utf-8"))
    data=client.recv(1024)
    print(data.decode())

client.close()



服務端
import socket
server=socket.socket()
server.bind(('localhost',1010) )
server.listen(5)
while True:    #如果沒有這個while循環(huán)那么一旦客戶端關(guān)閉連接,在linux父叙、mac系統(tǒng)上神郊,服務端一直收的都是空,陷入一個死循環(huán)趾唱。而在windows上就會報錯涌乳。
    conn,addr=server.accept()               #必須放在外面,如果放在里面,可以同時接兩個電話甜癞,但是只能說一句
    while True:
        data=conn.recv(1024)
        if not data:
            print("client lost!")
            break
        print(data.decode())
        conn.send(data.upper())

server.close()

  • 實例三:socket實現(xiàn)簡單ssh功能(處理大數(shù)據(jù))
客戶端
import socket
client=socket.socket()
client.connect(('localhost',9999))
while True:
    cmd = input(">>:").strip()
    if len(cmd) == 0:continue
    client.send(cmd.encode('utf-8'))
    cmd_res_size=client.recv(1024)      #接受命令返回結(jié)果的長度
    print("命令長度: ",cmd_res_size)
    recv_data = b''
    recv_size = 0
    while recv_size < int(cmd_res_size.decode()):
        data=client.recv(1024)
        recv_size += len(data)      #每次收到的結(jié)果很可能小于1024 所以這里必須用len判斷
        print(recv_size)
        recv_data+=data
    else:
        print("cmd res recive done!",recv_size)
        print(recv_data.decode())


client.close()
服務端
import socket
import os
server=socket.socket()
server.bind(('localhost',9999))
server.listen()

while True:
    conn,addr=server.accept()
    while  True:
        print("等待新指令")
        data=conn.recv(1024)
        if not data:
            print("客戶端已斷開夕晓!")
            break
        print("執(zhí)行指令:",data)
        cmd_res=os.popen(data.decode()).read()      #接受字符串,執(zhí)行結(jié)果也是字符串

        if len(cmd_res) == 0:
            cmd_res='cmd has no output!'
        #conn.send(str(len(cmd_res)).encode('utf-8'))
        conn.send(str(len(cmd_res.encode())).encode("utf-8")) # 整數(shù)不能直接encode得先str      先把大小發(fā)給客戶端
        conn.send(cmd_res.encode('utf-8'))

server.close()

  • 實例四:利用socket實現(xiàn)文件傳輸
服務端
import socket
import os,hashlib
server=socket.socket()
server.bind(('localhost',9999))
server.listen()

while True:
    conn,addr=server.accept()
    while  True:
        print("等待新指令")
        data=conn.recv(1024)
        if not data:
            print("客戶端已斷開带欢!")
            break
        cmd,filename=data.decode().split()
        if os.path.isfile(filename):
            f=open(filename,'rb')
            m=hashlib.md5()
            file_size=os.stat(filename).st_size
            conn.send(str(file_size).encode('utf-8'))   #發(fā)送文件大小
            conn.recv(1024)         #wait for ack
            for line in f:
                m.update(line)
                conn.send(line)
            f.close()
            conn.send(m.hexdigest().encode())       #send md5
            print(m.hexdigest())
        print('send done!')

server.close()
客戶端
import socket,hashlib
client=socket.socket()
client.connect(('localhost',9999))
while True:
    cmd = input(">>:").strip()
    if len(cmd) == 0:continue
    if cmd.startswith("get"):
        client.send(cmd.encode())
        server_response=client.recv(1024)
        print("文件大小",server_response)
        client.send("ready to recv file".encode())      #ack
        file_total_size = int(server_response.decode())
        rece_size=0
        filename=cmd.split()[1]
        f=open(filename + '.new',"wb")
        m=hashlib.md5()
        while rece_size < file_total_size:  #解決了粘包运授,有可能大于烤惊,就把MD5粘過來了
            if file_total_size-rece_size>1024:  #代表要收不止一次
                size=1024
            else:                               #最后一次,剩多少吁朦,收多少
                size=file_total_size-rece_size
            data=client.recv(size)
            rece_size +=len(data)
            m.update(data)
            f.write(data)
        else:
            new_file_md5=m.hexdigest()
            print(rece_size,file_total_size)
            f.close()
        server_file_md5 = client.recv(1024)
        print("server file md5", server_file_md5.decode())
        print("client file md5", new_file_md5)
client.close()

md5校驗
import hashlib
m=hashlib.md5()
m.update(b"test")
m.update(b'abc')
print(m.hexdigest())
m2=hashlib.md5()
m2.update(b'testabc')
print(m2.hexdigest())
#證明了逐行 md5 和一起md5的效果是一樣的
  • 實例五:通過socketserver實現(xiàn)并發(fā)處理
服務端
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):       #默認在父類里是空的柒室,客戶端所有的交互都是在handle里完成的
        while True:
            try:
                self.data=self.request.recv(1024).strip()           #ConnectionResetError
                print("{} wrote: ".format(self.client_address[0]))  #打印客戶端的ip地址
                print(self.data)
                # if not self.data:           #代表客戶端斷開
                #     print(self.client_address,"斷開了")
                #     break                     #在使用socket時候,windows上關(guān)閉客戶端會報錯逗宜,linux'會陷入無限循環(huán)而不報錯
                                                #所以 需判斷
                                                #而在socketserver上widows和linnux上斷開客戶端都會報ConnectionResetError
                                                #所以使用異常處理
                self.request.send(self.data.upper())
            except ConnectionResetError as e:
                print("err",e)
                break

#每一個客戶端的請求過來都會實例化我們新創(chuàng)建的類
if __name__ == '__main__':
    HOST,PORT = 'localhost', 6969
    # server=socketserver.TCPServer((HOST,PORT),MyTCPHandler)
    server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)  #多并發(fā)
    server.serve_forever()

項目:實現(xiàn)ftp服務

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雄右,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子纺讲,更是在濱河造成了極大的恐慌擂仍,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熬甚,死亡現(xiàn)場離奇詭異逢渔,居然都是意外死亡,警方通過查閱死者的電腦和手機乡括,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門肃廓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诲泌,你說我怎么就攤上這事盲赊。” “怎么了敷扫?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵哀蘑,是天一觀的道長。 經(jīng)常有香客問我葵第,道長绘迁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任卒密,我火速辦了婚禮脊髓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘栅受。我一直安慰自己将硝,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布屏镊。 她就那樣靜靜地躺著依疼,像睡著了一般荣挨。 火紅的嫁衣襯著肌膚如雪神帅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天桶唐,我揣著相機與錄音,去河邊找鬼误辑。 笑死沧踏,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的巾钉。 我是一名探鬼主播翘狱,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼砰苍!你這毒婦竟也來了潦匈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤赚导,失蹤者是張志新(化名)和其女友劉穎茬缩,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吼旧,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡凰锡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了圈暗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寡夹。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖厂置,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情魂角,我是刑警寧澤昵济,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站野揪,受9級特大地震影響访忿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜斯稳,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一海铆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挣惰,春花似錦卧斟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至竖幔,卻和暖如春板乙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拳氢。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工募逞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蛋铆,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓放接,卻偏偏與公主長得像刺啦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子透乾,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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