1. 程式人生 > >網路程式設計基礎【day09】:socket接收大資料(五)

網路程式設計基礎【day09】:socket接收大資料(五)

本節內容

1、概述

2、socket接收大資料

3、中文字元的坑

一、概述

  上篇部落格寫到了,就是說當伺服器傳送至客戶端的資料,大於客戶端設定的資料,則就會把資料服務端發過來的資料剩餘資料存在IO緩衝區中,那我們如何解決這個問題呢?

  有的同學就說了:

  1. 改大客戶端接收的資料的大小=>這個方案並不能解決問題,因為官方建議最多隻能接收8k的資料,那服務端傳送過來的資料大於8K咋辦,很顯然不行
  2. 客戶端可以多收幾次=>客戶端需要收多少次,才能把這個命令返回的結果全部收回來呢?並且怎麼確定這條命令返回的結果已經被全部收回來了呢?

  很明顯,上面第二種思路靠譜一點:就是說服務端給客戶端發資料之前,先計算一下給客戶端要發多少資料,我先判斷 len 一下,就 ok 了,先讓客戶端知道服務端傳送過來的大小,比如說發過來的是5k大小,客戶端接收到了這個5k大小以後,就知道需要接收多少次了,迴圈接收,直到5k資料全部接收完畢為止。

二、socket接收大資料

2.1、邏輯圖

 

2.2、邏輯程式碼

1、客戶端程式碼

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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 )   #接收命令的長度      print ( "命令結果大小:" ,cmd_res_size.decode())      recevied_size   =  0    #接收客戶端發來資料的計算器      recevied_data  =  b''   #客戶端每次發來內容的計數器      while  recevied_size <  int (cmd_res_size.decode()):   #當接收的資料大小 小於 客戶端發來的資料          cmd_res  =  client.recv( 1024 )          recevied_size  + =  len (cmd_res)   #每次收到的服務端的資料有可能小於1024,所以必須用len判斷          recevied_data  + =  cmd_res      else :          print (recevied_data.decode( "utf-8" , "ignore" ))          print ( "cmd res receive done ...." ,recevied_size)   client.close()

2、服務端程式碼

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import  socket,os   server  =  socket.socket() server.bind(( "localhost" , 9999 )) server.listen( 5 ) while  True :      conn,addr  =  server.accept()      print ( "new addr:" ,addr)      while  True :          data  =  conn.recv( 1024 )          if  not  data:              print ( "客戶端已斷開" )              break          print ( "執行指令:" ,data)          cmd_res  =  os.popen(data.decode()).read()          print ( "before send:" , len (cmd_res))          if  len (cmd_res)  = =  0 :              cmd_res  =  "cmd has no output...."          conn.send(  str ( len (cmd_res.encode())).encode() )   #傳送服務端傳送給客戶端資料的長度          conn.send(cmd_res.encode( "utf-8" ))    #傳送服務端的資料          print ( "send done" ) server.close()

上面的程式碼解決了上面部落格,客戶端接收大資料出現的疑難雜症,問題表現,請檢視:猛擊這裡 中的 socket接收大資料困惑。

三、中文字元的坑

3.1、客戶端接收資料大小和實際大小不一致

說明:客戶端在接收資料的大小會和實際資料帶下不一樣,感覺實際資料要比客戶端接收的資料要大,這是為什麼呢?我們先來看一下現象吧。

1、客戶端程式碼改動如圖:

2、服務端程式碼改動如圖:

3、實現的效果圖:

上面的兩個資料應該一樣的呀,為啥不一樣呢?為啥之前的就能一樣呢?

答:因為python用計算中文字元,按字元和位元組算的話,長度的值是不一樣的,一個  中文字元=3個位元組  ,如圖: