zoukankan      html  css  js  c++  java
  • 内置方法比较 tcpudp进阶 粘包

    补充

    魔术方法__eq____lt____gt__

    两个对象做==比较的时候会自动调用__eq__这个方法,<比较时调用的是__lt__,>比较时调用的是__gt__

     
     1 class Person(object):
     2      def __init__(self, name,age):
     3          self.name = name
     4          self.age = age
     5      def __eq__(self, other):
     6          return self.name == other.name and self.age == other.age
     7      def __gt__(self, other):
     8          print('执行gt啦')
     9      def __lt__(self, other):
    10          print('执行lt啦')
    11  alex = Person('alex',83)
    12  alex222 = Person('alex',84)
    13  print('-'*20)
    14  print(alex == alex222)

    alex22会被当做other参数传入方法,alex == alex222的结果就是return的返回值

    今日内容

    tcp协议的进阶

    服务端:

    • sk:存储的是本身向操作系统申请的资源(ip地址与端口)

    • conn:存储的是一个客户端和服务端的连接信息

    服务端方面,可以和多个客户端进行握手,可以和客户端一直通信,可退出

     1  import socket
     2  sk = socket.socket()
     3  sk.bind(('127.0.0.1',9001))
     4  sk.listen()
     5  6  while True:  # 为了和多个客户端进行握手
     7      conn,addr = sk.accept() # 能够和多个客户端进行握手了
     8      print('conn : ',conn)
     9      while True:
    10          send_msg = input('>>>')
    11          conn.send(send_msg.encode('utf-8'))
    12          if send_msg.upper() == 'Q':break
    13          msg = conn.recv(1024).decode('utf-8')
    14          if msg.upper() == 'Q': break
    15          print(msg)
    16      conn.close()    # 挥手 断开连接
    17 18  sk.close()      # 归还申请的操作系统的资源

    客户端方面,可以和服务端一直通信,可退出

     1  import socket
     2  sk = socket.socket()
     3  sk.connect(('127.0.0.1',9001))
     4  5  while True:
     6      msg = sk.recv(1024)
     7      msg2 = msg.decode('utf-8')
     8      if msg2.upper() == 'Q':break
     9      print(msg,msg2)
    10      send_msg = input('>>>')
    11      sk.send(send_msg.encode('utf-8'))
    12      if send_msg.upper() == 'Q':break
    13  sk.close()

    udp协议的编程

    语法

    新的方法:socket.socket(type = socket.SOCK_DGRAM),recvfrom,sendto

    服务端

    1  import socket
    2 3  sk = socket.socket(type = socket.SOCK_DGRAM)
    4  sk.bind(('127.0.0.1',9001))
    5  while True:
    6      msg,addr= sk.recvfrom(1024)
    7      print(msg.decode('utf-8'))
    8      msg = input('>>>')
    9      sk.sendto(msg.encode('utf-8'),addr)

    客户端

     1  import socket
     2  3  sk = socket.socket(type=socket.SOCK_DGRAM)
     4  server = ('127.0.0.1',9001)
     5  while True:
     6      msg = input('>>>')
     7      if msg.upper() == 'Q':break
     8      sk.sendto(msg.encode('utf-8'),server)
     9      msg = sk.recv(1024).decode('utf-8')
    10      if msg.upper() == 'Q':break
    11      print(msg)
    和tcp协议的区别

    不可靠,不面向连接,效率高

    粘包现象

    tcp协议的特点

    多条消息之间没有边界,有许多优化机制,例如会在操作系统(内核态)中增加一个缓存机制,会把传输的数据;网络最大带宽限制MTU=1500字节,所以会自动把传输的数据拆分发送,再拼接接收(udp也可以传送超过1500字节,但是还是有限制,不得超过一个界限)

    粘包是什么?

    发送过来的消息会粘连在一起,几条消息被合并成一条消息

    怎么发生

    发送端 : 两条消息都很短,发送的间隔时间也非常短

    接收端 : 多条消息由于没有及时接收,而在接收方的 缓存端堆在一起导致的粘包

    怎么处理—本质是设置边界
    自定义协议

    自定义前四个字节的数据是长度

    服务端

     1  import socket
     2  3  sk = socket.socket()
     4  sk.bind(('127.0.0.1',9001))
     5  sk.listen()
     6  7  conn,addr = sk.accept()
     8  msg1 = input('>>>').encode()
     9  msg2 = input('>>>').encode()
    10  num = str(len(msg1))  # '10001'
    11  ret = num.zfill(4)    # '0006'
    12  conn.send(ret.encode('utf-8'))
    13  conn.send(msg1)
    14  conn.send(msg2)
    15  conn.close()
    16  sk.close()

    客户端

     
     1 import socket
     2  3  sk = socket.socket()
     4  sk.connect(('127.0.0.1',9001))
     5  length = int(sk.recv(4).decode('utf-8'))
     6  msg1 = sk.recv(length)
     7  msg2 = sk.recv(1024)
     8  print(msg1.decode('utf-8'))
     9  print(msg2.decode('utf-8'))
    10 11  sk.close()
    struct模块

    通过struct模块把长度转换成固定的四个字节;在使用struct.unpack把四个字节转换成数字

    服务端

     1  import struct
     2  import socket
     3  4  sk = socket.socket()
     5  sk.bind(('127.0.0.1',9001))
     6  sk.listen()
     7  8  conn,addr = sk.accept()
     9  msg1 = input('>>>').encode()
    10  msg2 = input('>>>').encode()
    11  blen = struct.pack('i',len(msg1))
    12  conn.send(blen)
    13  conn.send(msg1)
    14  conn.send(msg2)
    15  conn.close()
    16  sk.close()

    客户端

     1 import time
     2 import struct
     3 import socket
     4 
     5 sk = socket.socket()
     6 sk.connect(('127.0.0.1',9001))
     7 length = sk.recv(4)
     8 length = struct.unpack('i',length)[0]
     9 msg1 = sk.recv(length)
    10 msg2 = sk.recv(1024)
    11 print(msg1.decode('utf-8'))
    12 print(msg2.decode('utf-8'))
    13 
    14 sk.close()
  • 相关阅读:
    洛谷——P1951 收费站_NOI导刊2009提高(2)
    洛谷——P1475 控制公司 Controlling Companies
    洛谷——P1176 路径计数2
    洛谷——P1156 垃圾陷阱
    洛谷——P2734 游戏 A Game
    洛谷——P1767 家族_NOI导刊2010普及(10)
    洛谷——P1413 坚果保龄球
    Kali-linux破解LM Hashes密码
    Kali-linux分析密码
    Kali-linux密码在线破解
  • 原文地址:https://www.cnblogs.com/zhangxiangning/p/10446009.html
Copyright © 2011-2022 走看看