Python--day32--复习:https和http的区别;黏包;黏包问题的解决方式;

1,https和http的区别:

  https比较安全,传输的时候先对内容进行加密,收到后再进行解密;它的传输内容不容易拦截,就算拦截下来了,也是加密的,看不懂。但是要买证书,一年要好几万,小公司承担不起。听说非常安全,在业内都没有出过问题。

2,udp不会黏包,只有tcp会黏包

  传输的时候只能传输bite类型数据

  demo1--远程执行命令:

server.py

sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()
conn,addr = sk.accept()
while True:
    cmd = input('>>>')
    if cmd == 'q':
        conn.send(b'q')
        break
    conn.send(cmd.encode('gbk'))
    res = conn.recv(1024).decode('gbk')
    print(res)
conn.close()
sk.close()

client.py

#接收server端的命令之后在自己的机器上执行
import socket
#找个什么人去帮你执行程序
import subprocess

#创建一个sokect的对象
sk = socket.socket()
sk.connect(('127.0.0.1', 8080))
while True:
    #收1024个字节
    cmd = sk.recv(1024).decode('gbk')
    if cmd == 'q':
        break
    #把接收的结果预先存到PIPE管道里面,就是装数据的容器
    res = subprocess.Popen(cmd,shell=True,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)
    sk.send(res.stdout.read())
    sk.send(res.stderr.read())
sk.close()

黏包现象:

 

3、什么是黏包问题,这里终于讲清楚了:

黏包(是tcp协议内部的优化算法造成的):

  client接收数据的时候,分两次接收,第一次接收的时候假如只接收两个的话,第二次接收的时候就不会接收得到十个数据,只能接收掉了八个数据。

  如果是udp,第一次接收了两个数据,第二次接收是接收不到数据的,因为后面八位数据已经丢失了。

  只有tcp中有缓存机制才能发生第二次接收的时候从缓存中接收到剩下的机制,这种现象就是黏包现象。第一次没有完全接收,第二次就会把剩下的发给我,这种问题就是黏包问题

  现在用到的所有的网络传输都是基于socket的

 

   #优化算法

  #连续的小数据包会被合并

  #多个send 小的数据连在一起,会发生黏包现象,是tcp协议内部的优化算法造成的

  #连续使用了send

  client端发送信息的机制:

    当把所需要的消息发送完关闭之后,默认再往服务器发送一个空消息。(比较高点版本的Windows系统会发送空消息,比较低版本的Windows系统直接报错,我在win7下测试发送的也是空消息)

  client2.py

  server2.py

  #在tcp优化算法中,只有在非常短的时间内接收到消息,才会发生黏包,

  #如果等了一段时间,比如一个网络延时了,就会先发先走

  server2.py

  client2.py

4、发生黏包的原因:

  1,连续send两个小数据

  2,两个recv,第一个recv特别小

  #发生黏包的本质就是你不知道到底要接收多大的数据

 

5、黏包问题的解决方式

  1,方法1:

    首先:发送一下这个数据到底有多大

    再按照数据的长度接收数据

  #好处:确定了我到底要接收多大的数据
  #要在文件中配置一个配置项:就是每一次recv的大小 buffer = 4096
  #当我们要发送大数据的时候,要明确的告诉接收方要发送多大的数据,以便接收方能够准确的接收到所有的数据
  #多用在文件传输的过程中
  #大文件的传输 一定是按照字节读 每一次读固定的字节
  #传输的过程中 一边读一边传 接收端 一边收一边写
  #send这个大文件之前,35672字节 send(4096) 35672-4096-4096 -->0
  #recv这个文件,recv 35672字节 recv(2048) 35672-2048 -->0


  #不好的地方:多了一次交互
  #send sendto 在超过一定的范围的时候 都会报错
  #程序的内存管理
  程序:
  client.py
 1 #接收server端的命令之后在自己的机器上执行
 2 import socket
 3 #找个什么人去帮你执行程序
 4 import subprocess
 5 
 6 #创建一个sokect的对象
 7 sk = socket.socket()
 8 sk.connect(('127.0.0.1', 8080))
 9 while True:
10     #收1024个字节
11     cmd = sk.recv(1024).decode('gbk')
12     if cmd == 'q':
13         break
14     #把接收的结果预先存到PIPE管道里面,就是装数据的容器
15     res = subprocess.Popen(cmd,shell=True,
16                      stdout=subprocess.PIPE,
17                      stderr=subprocess.PIPE)
18     std_out = res.stdout.read()
19     std_err = res.stderr.read()
20     sk.send(str(len(std_out)+len(std_err)).encode('utf-8'))#2000
21     #这里一般不超过4096个,过大会给运行内存造成巨大的压力
22     sk.recv(4096)   #ok
23     sk.send(std_out)
24     sk.send(std_err)
25 sk.close()

  server.py

 1 #server 下发命令 给client
 2 
 3 import socket
 4 sk = socket.socket()
 5 sk.bind(('127.0.0.1', 8080))
 6 sk.listen()
 7 conn,addr = sk.accept()
 8 while True:
 9     cmd = input('>>>')
10     if cmd == 'q':
11         conn.send(b'q')
12         break
13     conn.send(cmd.encode('gbk'))
14     num = conn.recv(1024).decode('utf-8')
15     conn.send(b'ok')
16     res = conn.recv(int(num)).decode('gbk')
17     print(res)
18 conn.close()
19 sk.close()

   2,方法2:struct模块解决黏包问题(看红色的代码)

      init.py

 1 import struct
 2 
 3 ret = struct.pack('i', 4096) #‘i’代表int,就是即将要把一个数字转换成固定长度bytes类型
 4 print(ret)
 5 
 6 num = struct.unpack('i', ret)
 7 print(num[0])
 8 
 9 #如果发送数据的时候
10 #先发送长度  先接收长度

      server.py

 1 import struct
 2 import socket
 3 sk = socket.socket()
 4 sk.bind(('127.0.0.1', 8080))
 5 sk.listen()
 6 conn,addr = sk.accept()
 7 while True:
 8     cmd = input('>>>')
 9     if cmd == 'q':
10         conn.send(b'q')
11         break
12     conn.send(cmd.encode('gbk'))
13     num = conn.recv(4)  #2048
14     num = struct.unpack('i', num)[0]    #2048
15     res = conn.recv(int(num)).decode('gbk')
16     print(res)
17 conn.close()
18 sk.close()

    client.py

 1 import struct
 2 import socket
 3 #找个什么人去帮你执行程序
 4 import subprocess
 5 
 6 #创建一个sokect的对象
 7 sk = socket.socket()
 8 sk.connect(('127.0.0.1', 8080))
 9 while True:
10     #收1024个字节
11     cmd = sk.recv(1024).decode('gbk')
12     if cmd == 'q':
13         break
14     #把接收的结果预先存到PIPE管道里面,就是装数据的容器
15     res = subprocess.Popen(cmd,shell=True,
16                      stdout=subprocess.PIPE,
17                      stderr=subprocess.PIPE)
18     std_out = res.stdout.read()
19     std_err = res.stderr.read()
20     len_num = len(std_out)+len(std_err)
21 
22     num_by = struct.pack('i', len_num)
23     sk.send(num_by) #4  2048
24     sk.send(std_out)#1024
25     sk.send(std_err)#1024   4+2048
26 sk.close()

 

 

 

posted @ 2019-01-20 20:14  莱茵河的雨季  阅读(253)  评论(0编辑  收藏  举报