网络编程-tcp-udp协议

软件开发架构

c\s架构
clitent: 客户端

​ server:服务端

b\s架构

​ Browser:浏览器

​ server:服务端

计算机与计算机想要实现远程通信,除物理介质外还需以来一个共同标准的方式==》》互联网协议

osi七层模型(协议)

​ 应用层

​ 表示层

​ 会话层

​ 传输层

​ 网络层

​ 数据链路层

​ 物理连接层

开发人员优先掌握五层

​ 应用层

​ 传输层

​ 网络层

​ 数据链路层

​ 物理连接层

'''
1.物理连接层:
        实现计算机之间物理连接,传输的数据都是01010的二进制
        电信号工作原理:电只有高低电平
2.数据链路层("以太网协议"!):
    1.规定了二进制数据的分组方式
    2.规定了只要是接入物联网的计算机,都必须有一块网卡!
    网卡上面刻有世界唯一的编号:
        每块网卡出厂时都被烧制上一个世界唯一的mac地址,
        长度为48位2进制,通常由12位16进制数表示(前六位是厂商编号,后六位是流水线号)
        我们管网卡上刻有的编号叫电脑的>>>mac地址
        ----->上面的两个规定其实就是 "以太网协议"!
基于以太网协议通信:通信基本靠吼!!!
    弊端:广播风暴
    
    交换机:如果没有交换机,你的电脑就变成了马蜂窝,有了交换机之后,所有的电脑只需要有一个网卡连接交换机
    即可实现多台电脑之间物理连接
    
    
    3.网络层(IP协议)
        规定了计算机都必须有一个ip地址
            ip地址特点:点分十进制
            有两个版本ipv4和ipv6 为了能够兼容更多的计算机
            最小:0.0.0.0     
            最大:255.255.255.255
        IP协议可以跨局域网传输
        
        ip地址能够唯一标识互联网中独一无二的一台机器!
            
    
            
    4.传输层(端口协议)
        TCP,UDP基于端口工作的协议!
        其实计算机之间通信其实是计算机上面的应用程序于应用之间的通信
        端口(port):唯一标识一台计算机上某一个基于网络通信的应用程序
        端口范围:0~65535(动态分配)
            注意:0~1024通常是归操作系统分配的端口号
            通常情况下,我们写的软件端口号建议起在8000之后
            flask框架默认端口5000
            django框架默认端口8000
            mysql数据库默认端口3306
            redis数据库默认端口6379
        注意:一台计算机上同一时间一个端口号只能被一个应用程序占用
    
    小总结:
        IP地址:唯一标识全世界接入互联网的独一无二的机器
        port端口号:唯一标识一台计算机上的某一个应用程序
        ip+port :能够唯一标识全世界上独一无二的一台计算机上的某一个应用程序
    
    补充:
        arp协议:根据ip地址解析mac地址 
    
    
    应用层(HTTP协议,FTP协议):
        
    
    
    TCP协议(流式协议,可靠协议)
        三次握手四次挥手
            三次握手建连接
            
            四次挥手断连接
            
            星轨:明星出轨
'''

为什么会出现粘包现象

"""
首先只有在TCP协议中才会出现粘包现象,因为TCP协议是流式协议
它的特点是将数据量小并且时间间隔比较短的数据一次性打包发送出去
本质其实还是因为我们不知道需要接收的数据的长短
"""
# 如何解决粘包问题?
# 1 发送数据直接先告诉对方数据量的大小
# 2 利用struct模块定制我们自己的消息传输协议

socket发送大文件示例

# 客户端
import struct
import json
import socket
import os

client = socket.socket()
client.connect(('127.0.0.1', 8080))

file_size = os.path.getsize(r'/Users/jiboyuan/PycharmProjects/aboutsocket/10 解决粘包问题终极版.mp4')
file_path = r'/Users/jiboyuan/PycharmProjects/aboutsocket/10 解决粘包问题终极版.mp4'
data_dic = {
    'file_name': '澳门最大线上赌场开业啦.mp4',
    'file_size': file_size
}
header_json = json.dumps(data_dic)
header_bytes = header_json.encode('utf-8')
# 制作字典的报头
header = struct.pack('i', len(header_bytes))
# 发送报头
client.send(header)
# 发字典数据
client.send(header_bytes)
# 打开文件发送文件数据
with open(file_path,'rb') as f:
    for line in f:
        client.send(line)

# 服务端
import socket
import json
import struct

server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    while True:
        try:
            header = conn.recv(4)
            if len(header) == 0:break
            dic_len = struct.unpack('i', header)[0]

            real_dic = json.loads(conn.recv(dic_len).decode('utf-8'))
            print(real_dic)
            file_name = real_dic.get('file_name')
            file_size = real_dic.get('file_size')
            recv_size = 0
            with open(file_name, 'wb') as f:
                while recv_size < file_size:
                    recv_data = conn.recv(1024)
                    f.write(recv_data)
                    recv_size += len(recv_data)
        except ConnectionResetError:
            break

UDP协议

"""
1.udp协议客户端允许发空
2.udp协议不会粘包
3.udp协议服务端不存在的情况下,客户端照样不会报错
4.udp协议支持并发

UDP叫数据报协议,意味着发消息都带有数据报头
udp的server不需要就行监听也不需要建立连接
在启动服务之后只能被动的等待客户端发送消息过来,客户端发送消息的时候,要带上服务端的地址
服务端在回复消息的时候,也需要带上客户端的地址
"""
# 服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))

msg, addr = server.recvfrom(1024)
print(msg.decode('utf-8'))
server.sendto(b'hello', addr)

server.close()

#客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)

client.sendto(b'hello server baby!', server_addr)
msg, addr = client.recvfrom(1024)
print(msg, addr)


# udp特点 >>> 无链接,类似于发短信,发了就行对方爱回不回,没有任何关系
# 将服务端关了,客户端起起来照样能够发数据。因为不需要考虑服务端能不能收到

# 验证udp协议有无粘包问题
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
print(server.recvfrom(1024))
print(server.recvfrom(1024))
print(server.recvfrom(1024))

import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1',8080)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)

基于UDP实现简易版本的qq

# 服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
while True:
    msg, addr = server.recvfrom(1024)
    print(addr)
    print(msg.decode('utf-8'))
    info = input('>>>:').encode('utf-8')
    server.sendto(info, addr)

server.close()

# 多个客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)

while True:
    info = input('>>>:')
    info = ('来自客户端1的消息:%s'%info).encode('utf-8')  # 改中文备注即可
    client.sendto(info, server_addr)
    msg, addr = client.recvfrom(1024)
    print(msg.decode('utf-8'), addr)

client.close()

小知识点补充:

windows电脑和max电脑的时间同步功能,其实就是基于udp朝windows,max服务器发送请求获取标准时间

总结:

TCP协议就类似于打电话

UDP协议就类似于发短信

猜你喜欢

转载自www.cnblogs.com/zhouyixian/p/10833302.html