TCP中的粘包问题,以及用TCP和UDP实现多次聊天

TCP协议

在连接内多和客户端说几句

#server端
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()

while True
    conn,addr = sk.accept()
    while True
        bad = input('>>>')
        conn.send(bad.encode('utf-8'))
        if bad.upper() == 'Q':
            break
        msg = conn.recv(1024).decode('utf-8')
        if msg.upper == 'Q':break
        print(msg)
	conn.close()  #挥手 断开连接
    
sk.close() #归还申请的操作系统资源
#client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9001))

while True:
    msg = sk.recv(1024)
    msg2 = msg.decode('utf-8')
    if msg2.upper == 'Q':break
    print(msg2)
    send_msg = input('>>>')
    sk.send(send_msg.encode('uft-8'))
    if send_msg.upper == 'Q':break
sk.close()

为什么要加while True

  1. 因为要进行多次通信

sk代表什么?

  1. sk代表启用的通信服务

conn代表什么?

  1. conn代表自己的IP地址,和对方的地址和端口

能够接受多个客户端的请求

  1. 为什么加while True
    1. 因为在一个客户端断开连接之后不能管不服务,要等待另一个客户端连接
  2. 怎么退出
    1. 在接收或者传输的时候先检查是不是要退出,要是退出的话就break

UDP协议

语法:

#server
import socket
sk = socket.socket(tyep = socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',9000))

msg,addr = sk.recvfrom(1024)
print(msg.decode('utf-8'))
msg = input('>>>')
sk.sendto(msg.encode('utf-8'),addr)

#client
import socket
sk = socket.socket(type = socket.SOCK_DGRAM)
server = ('127.0.0.1',9000)
while True:
    msg = input('>>>')
    if msg.upper == 'Q':break
    sk.sendto(msg.encode('utf-8'),server)
    msg = sk.recv(1024).decode('utf-8')
    if msg.upper() == 'Q':break
    print(msg)

涉及到的新方法

  1. type = socket.SOCK_DGRAM 在开启socket方法的时候加上这段代码,表示就是用UDP协议
  2. recvfrom:在server端接收信息的时候用recvfrom就可以把客户机的IP地址获取到

和TCP协议的区别

  1. 它可以同时建立多个连接,当一个连接断开后不会影响其他连接

粘包现象

  1. TCP协议的特点
    1. 多条消息之间没有边界,并且还有一大堆优化算法
  2. 什么叫做粘包
    1. 多条数据粘在一起
  3. 为什么会出现粘包
    1. 发送端:两条消息都很短,发送的间隔时间也非常短
    2. 接收端:多条消息由于没有及时接收,而在接收方的缓存短堆在一起导致粘包
  4. 怎么处理
#server
import struct
import socket

sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()

conn,addr = sk.accept()
msg1 = input('>>>').encode()
msg2 = input('>>>').encode()
blen = struct.pack('i',len(msg1))
conn.send(blen)
conn.send(msg1)
conn.send(msg2)
sk.close()

#cilent
import struct
import socket

sk = socket.socket()
sk.connect(('127.0.0.1',9001))
length = sk.recv(4)
length = struct.unpack('i',length)[0]
msg1 = sk.recv(length)
msg2 = sk.recv(1024)
print(msg1.decode('utf-8'))
print(msg2.decode('utf-8'))

sk.close()

什么叫自定义协议

  1. 在网络传输的时候,人为的为它定制一个协议,让它遵守此项协议

struct模块怎么用

  1. struct.pack()#将一个数字转换为4个字节的数
  2. struct.unpack()#将一个4个字节的数,转化回原来的数

osi五层协议

  • 应用层
  • 传输层
    • tcp协议:效率低 面向连接、可靠、全双工的通信
      • 三次握手
        • 客户端向服务器端发送syn请求
        • 服务器端向客户端回复ack并发送syn请求
        • 客户端接收到的请求之后再回复ack表示建立连接
        • 由客户端的connect + 服务端的 close
      • 四次挥手
        • 客户端向服务端发送fin请求
        • 服务端回复ack确认
        • 服务端向客户端发送fin请求
        • 客户端回复ack
        • 由客户端的close和服务端的close
    • udp协议:效率高 无连接的、不可靠
    • 四层交换机,四层路由器
  • 网络层
    • IP协议(ipv4,ipv6)
    • 路由器、三层交换
  • 数据链路层
  • arp协议,地址解析协议 通过IP找到mac地址
  • 物理层
原文地址:https://www.cnblogs.com/wang-xing-hao/p/11172741.html