1. 程式人生 > >網路程式設計基礎【day09】:socket解決粘包問題之MD5(八)

網路程式設計基礎【day09】:socket解決粘包問題之MD5(八)

本節內容

1、概述

2、程式碼實現

一、概述

  上一篇部落格講到的用MD5來校驗還是用的之前解決粘包的方法,就是客戶端傳送一個請求,等待服務端的確認的這樣的一個笨方法。下面我們用另外一種方法:就是客戶端已經知道可接收多少資料了,既然客戶端已經知道接收多少資料了,那麼客戶端在接收資料的時候,正好接收已經知道的資料,不就ok了嗎?就是說我迴圈了正好是收到已經知道的那些資料。比如:我要發5M的資料,我正好收到5M的資料,然後就不往下再收了,因為它有可能跟MD5值黏在一塊了,本來說是發5M檔案,結果你發了5.1M,那麼客戶端正好收5M的話,那客戶端的0.1M是不是就不收了,不收了之後我就把客戶端把檔案存下來,再來recive一下,下面recive的正好是0.1M。

二、程式碼實現

說明:其實我們在接收檔案時,只有最後一次才會超過接收大小,所以我們從這裡下手

2.1、服務端程式碼

說明:生成md5物件->傳送的資料生成MD5值->傳送MD5 值

①程式碼

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import  hashlib import  socket,os   server  =  socket.socket() server.bind(( "localhost" , 9999
)) server.listen() while  True :      conn,addr  =  server.accept()      print ( "new conn:" ,addr)      while  True :          print ( "等待新指令" )          data  =  conn.recv( 1024 )          if  not  data:              print ( "客戶端已斷開" )              break          cmd,filename  =  data.decode().split()          print (filename)          if  os.path.isfile(filename):              =  hashlib.md5()   #生成MD5的物件              with  open (filename, "rb" ) as f:                  file_size  =  os.stat(filename).st_size                  conn.send(  str (file_size).encode() )  #send file size                  conn.recv( 1024 )                  for  line  in  f:                      m.update(line)   #計算md5值                      conn.send(line)   #傳送資料至客戶端                  print ( "file md5" ,m.hexdigest())              conn.send(m.hexdigest().encode())   #生成MD5值並且傳送給客戶端          print ( "send done" )   server.close()

②程式碼改動

2.2、客戶端

說明:檔案大小-接收大小是否大於1024 ->獲取size值->recive(size)->下面再次recive時就是MD5值了

①程式碼

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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_respose  =  client.recv( 1024 )          print ( "server response:" ,server_respose)          client.send( "ready to recv file" .encode())          file_total_size  =  int (server_respose.decode())          revived_size  =  0          filename  =  cmd.split()[ 1 ]          =  hashlib.md5()   #生成MD5物件          with  open (filename  +  ".new" , "wb" ) as f:              while  revived_size < file_total_size:                  if  file_total_size  -  revived_size >  1024 :   #要收不止一次                      size  =  1024                  else :   #最後一次,剩多少收多少                      size  =  file_total_size  -  revived_size                      print ( "last receive:" ,size)                  data  =  client.recv(size)                  revived_size  + =  len (data)                  m.update(data)    #計算資料接收的MD5值                  f.write(data)              else :                  print (file_total_size,revived_size)                  new_file_md5  =  m.hexdigest()   #生成接收資料的MD5值16進位制形式          server_file_md5  =  client.recv( 1024 )   #接收客戶端的MD5值          print ( "server file md5:" ,server_file_md5.decode())          print ( "client file md5:" ,new_file_md5) client.close()

 ②程式碼改動

2.3、思路圖

2.4、實現的效果圖