魔术方法__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()