网络编程

[doc]

一、网络编程大体图

二、TCP协议

TCP协议又叫:流失协议、可靠协议

1.TCP协议像流水一样一直发送,一直接收

2.TCP协议可靠的原因:有反馈机制(发送一句,回复一句才会发送下一句)

洪水攻击:同一时间发送给服务器大量请求

1.三次握手,四次挥手图

2.tcp代码

1.简单版

服务端:

import socket

server = socket.socket()  # 生成对象
server.bind(('127.0.0.1', 8080))  # 绑定IP和端口 (自己的)
server.listen(5)  # 半连接池,允许等待数

conn, addr = server.accept()  # 等待接听
# conn:地址 addr:端口号(随机分配)

while True:
    data = conn.recv(1024)  # 接收
    print(data)  # 打印接收的内容
    # 判断如果接收的是空,就跳出循环
    if len(data) == 0:
        break
    conn.send(data.lower())  # 发送反馈内容

客户端:

import socket

client = socket.socket()  # 生成对象
client.connect(('127.0.0.1', 8080))  # 拨号,对方IP和端口

while True:
    msg = input('请输出 >>>:').strip().encode('utf-8')  # 转二进制
    if len(msg) == 0:
        continue
    client.send(msg)  # 发送
    data = client.recv(1024)  # 接收反馈内容
    print(data)

2.电影上传

1.打包,固定长度模块struct

注意:一般用'i'模式,固定4个字节 长度,q模式最大8个字节长度

import struct
"""
利用struct给
"""
res1 = 'asdfkjhksdhfksadhfkkshfasjdfklasddfjkl'
print('开始的', len(res1))
res2 = struct.pack('i', len(res1))
print('压缩的', len(res2))

res3 = struct.unpack('i', res2)[0]
print('解压的', res3)

客户端:

import os
import socket
import struct
import json

move = socket.socket()  # 生成对象
move.connect(('127.0.0.1', 8080))  # 写服务端的IP,port

while True:
    # 1.拼接文件路径
    MOVE_PATH = r'E:学习视频python老男孩对象day20视频'
    move_list = os.listdir(MOVE_PATH)

    # 循环打印
    for i in move_list:
        print(move_list.index(i)+1, i)
    # 用户选择
    choice = input('请选择你要上传的电影>>>:')
    # 判断输入是否为数字
    if choice.isdigit():
        # 转成int型
        choice = int(choice)-1
        # 判断是否在范围内
        if choice in range(0, len(move_list)):
            # 拿到用户选择的文件
            move_choice = move_list[choice]
            # 拼接文件路径
            move_path = os.path.join(MOVE_PATH, move_choice)
            # 拿到文件大小
            move_size = os.path.getsize(move_path)
            # 定义字典容器,数据放到字典中
            move_dict = {'name': '陪你到老.mp4', 'size': move_size}
            # 转成json格式和转成二进制格式的字典
            json_dict = json.dumps(move_dict).encode('utf-8')
            # 制作字典报头
            hander_dict = struct.pack('i', len(json_dict))

            # 发送报头
            move.send(hander_dict)
            # 发送字典
            move.send(json_dict)

            # 发送文件
            with open(move_path, 'rb')as f:
                for i in f:
                    move.send(i)
        else:
            print('你选的不在范围内')
    else:
        print('请输入数字')

服务端:

import os
import socket
import json
import struct

server = socket.socket()  # 生成对象
server.bind(('127.0.0.1', 8080))  # 绑定IP,port
server.listen(5)  # 半连接池

while True:
    data, addr = server.accept()  # 接受连接
    # print(data, addr)
    while True:
        try:
            # 接收字典报头
            dict_hand = data.recv(4)
            # 解析字典报头,拿到字典长度
            dict_len = struct.unpack('i', dict_hand)[0]
            # 接收字典长度,就是接收字典
            dict_json = data.recv(dict_len)
            # 解开json,解码二进制
            dict = json.loads(dict_json.decode('utf-8'))
            # 从字典中获取文件的大小长度
            move_size = dict.get('size')
            # 循环接收,并写入文件
            accept_size = 0
            # print(dict.get('name'))

            with open(dict.get('name'), 'wb')as f:
                while accept_size < move_size:
                    accept = data.recv(1024)
                    f.write(accept)  # 写入文件
                    accept_size += len(accept)
                print('上传成功')
        except ConnectionResetError as f:
            print(f)
            break
    data.close()

3.json补充,序列化类

from datetime import *
import json

"""序列化类.先转换成字符串型,才能序列化"""

# 1.手动转化成字符串型
b = str(datetime.today())
c = str(date.today())
a = {'1':b,'2':c}
# print(json.dumps(a))
d = str(datetime.today().strftime('%Y-%m-%d'))
# print(d)
e = type(datetime.today())
print(e)



# 2.定义一个继承json的新的类
class MyJson(json.JSONEncoder):
    def default(self, o):
        if isinstance(o,datetime):
            return o.strftime('%Y-%m-%d %X')
        elif isinstance(o,date):
            return o.strftime('%Y-%m-%d')
        else:
            return super().default(self,o)
res = json.dumps(a)
print(res)

4.subprocess补充

import subprocess


cmd = input('输入命令>>>:')
obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
print(obj.stdout.read().decode('gbk'))  # 正确命令返回结果
print(obj.stderr.read().decode('gbk'))  # 错误命令返回结果


#  subprocess获取到的数据  拿完就没有了  不能重复拿

三、UDP的使用

1.简介

udp协议又叫:

​ 1.数据报协议(自带报头)

​ 2.没有双向通道

​ 3.也没有半连接池

发送数据就类似发短信,给指定的IP,port发送,不用管对方有没有收到

​ 缺点:容易数据丢失,不安全

​ 优点:速度快

2.使用基本代码

服务端:

import socket

server = socket.socket(type=socket.SOCK_DGRAM)  # UDP协议
server.bind(('127.0.0.1', 8080))   # 绑定自己的地址端口


while True:
    data, addr = server.recvfrom(1024)  # 接收
    print('接收到数据:', data)
    print('地址:', addr)
    server.sendto(data.upper(), addr)   # 发送

客户端:

import socket

client = socket.socket(type=socket.SOCK_DGRAM)

server = ('127.0.0.1', 8080)  # 要发送的地址端口
while True:
    client.sendto(b'hello', server)  # 发送
    data, addr = client.recvfrom(1024)   # 接收
    print(data)  # 打印

2.1简易版qq

服务端:

import socket

phone = socket.socket(type=socket.SOCK_DGRAM)  # 1.建立对象
addres = ('127.0.0.1', 8080)

while True:
    send = input('请输入要发送的内容>>>:').encode('utf-8')
    phone.sendto(send, addres)  # 2.发送内容,填写地址
    data, addr = phone.recvfrom(1024)  # 3.接收
    print('收到内容:', data.decode('utf-8'))  # 4.接收转码


客户端:

import socket

server = socket.socket(type=socket.SOCK_DGRAM)  # 1.建立对象
server.bind(('127.0.0.1', 8080))  # 2.绑定地址

while True:
    data, addr = server.recvfrom(1024)  # 3.接收
    print('收到的内容:', data.decode('utf-8'))  # 4.打印,解码
    print('对方地址:', addr)  # 打印,解码
    msg = input('请输入你要回复的内容>>>:').encode('utf-8')
    server.sendto(msg, addr)  # 5.回复发送

四、UDP和TCP的区别

UDP:类似发短信(只管往某个电话发短信,不管对方有没有看)

​ 1.允许发空(自带报头)

​ 2.不会粘包(自带报头)

​ 3.UDP支持并发

​ 4.UDP服务协议不安全(没有三次握手)

​ 5.UDP速度更快

TCP:类似打电话(有人接听,有人回复)

​ 1.不允许发空(没有报头)

​ 2.会粘包(没有报头)

​ 3.安全系数高(有三次握手)

原文地址:https://www.cnblogs.com/WQ577098649/p/11887459.html