二十四、网络编程

网络编程

  • 一 软件开发架构
    • 1 c/s架构
    • 2 b/s架构
  • 二 网络编程
    • 2.1 概述
    • 2.2 OSI七层参考模型
    • 2.3 网络相关名词
  • 三 socket通信
  • 练习
  • 四 UDP协议
  • 五 操作系统的发展史
  • 六 多道技术

一 软件开发架构

1 c/s架构

c就是客户端(client),s就是服务器(server)
计算机中下载的app软件其实就是客户端,下载客户端就是为了体验相应服务端的功能。

服务器应该具备的性质?

  1. 一般不会停止运行
  2. 地固定的地址
  3. 能够让多个客户端同时访问

2 b/s架构

b就是浏览器(browser),b/s架构本质就是c/s架构。

c/s架构的优缺点:
优点:可以使用服务器完整的功能
缺点:需要下载相应的客户端

b/s架构的优缺点:
优点:不用下载客户端
缺点:功能不完善

二 网络编程

2.1 概述

计算机网络:是将地理位置不同的多台计算机通过通信线路连接起来,实现资源和信息的传递。
网络编程:是用来实现网络互联的不同计算机上运行的程序可以进行数据交换。

2.2 OSI七层参考模型

  1. 物理层:主要定义物理设备标准,用来传递比特流。
  2. 数据链路层:主要讲物理层接受到的数据进行MAC地址(网卡)的封装和解封。常把这一层的数据称作为帧,在这一层工作的是交换机,数据通过交换机传输。
  3. 网络层:IP协议规定了任何接入网络的计算机都要有一个IP地址
  4. 传输层:PORT协议规定每一台计算机上运行的程序都必须有一个端口号,计算机用来管理多个应用程序的标记,端口范围:0-65535
    tcp协议:tcp协议是面向连接的,可靠的传输。三次握手四次分手
    udp协议:没有tcp安全,传输效率较高。
    应用层:主要取决于程序员自己采用的策略和协议。
    二十四、网络编程_第1张图片

2.3 网络相关名词

  1. 交换机
    能够让连接到交换机的多台计算机实现彼此互联
  2. 以太网通信(mac通信)
    有了交换机之后,根据电脑的mac地址就可以实现数据交互,mac通信仅限于局域网内
  3. 局域网
    某个区域组成的网络
  4. 路由器
    将多个局域网连接到一起的设备

三 socket通信

服务器

# 导入socket模块
import socket

# 创建一个socket对象
ser = socket.socket()

# 绑定IP和端口
ser.bind(('127.0.0.1', 8080))

# 半连接池
ser.listen(5)

# 接受客户端的连接
sock, addr = ser.accept()

# 向客户端发送消息
sock.send('服务端发送消息'.encode('utf8'))

# 接受客户端的消息
res = sock.recv(1024)
print(res.decode('utf8'))

客户端

import socket

client = socket.socket()

# 连接服务器
client.connect(('127.0.0.1', 8080))

# 接收消息
res = client.recv(1024)
print(res.decode('utf8'))

# 发送消息
client.send('这是客户端发送消息'.encode('utf8'))

练习

编写一个cs架构的软件
就两个功能
一个视频下载:从服务端下载视频
一个视频上传:从客户端上传视频

服务器

import socket
import struct
import json
import os


server = socket.socket()

server.bind(('192.168.1.193', 8080))
server.listen(5)

sock, addr = server.accept()
print(sock, addr)
BASE_DIR = os.path.dirname(__file__)

DB_BASE_DIR = r'C:\Users\xuxiaoxu\Documents\WeChat Files\wxid_0cwbtnrkk7cp31\FileStorage\Video\2022-08'

data_dict = {}
while True:
    mode = sock.recv(struct.unpack('i', sock.recv(4))[0]).decode()
    if mode == '1':
        name_list = os.listdir(DB_BASE_DIR)
        for i, v in enumerate(name_list, start=1):
            i = str(i)
            data_dict[i] = v
        res = json.dumps(data_dict).encode('utf8')
        hard = struct.pack('i', len(res))
        sock.send(hard)
        sock.send(res)
        # 接受客户端编号报头并拆包
        input_id = sock.recv(struct.unpack('i', sock.recv(4))[0]).decode()
        file_name = name_list[int(input_id) - 1]
        # 发送用户选择的文件数据字典
        file_dict = {
            'file_name': file_name,
            'file_size': os.path.getsize(os.path.join(DB_BASE_DIR, file_name))
        }
        # print(file_dict['file_size'])
        to = json.dumps(file_dict).encode()
        f_hard = struct.pack('i', len(to))
        sock.send(f_hard)
        sock.send(to)
        # 发送用户选择的真正文件
        file_path = os.path.join(DB_BASE_DIR, file_name)
        with open(file_path, 'rb') as f:
            for file in f:
                sock.send(file)
        print('发送完成')
    else:
        c_dict = json.loads(sock.recv(struct.unpack('i', sock.recv(4))[0]).decode('utf8'))
        name = c_dict.get('c_file_name')
        size = c_dict.get('c_file_size')
        c_size = 0
        new_name = name.split('\\')[-1]
        with open(os.path.join(BASE_DIR, new_name), "wb") as f:
            while c_size < size:
                real_file = sock.recv(1024)
                f.write(real_file)
                c_size += len(real_file)
        print('数据接收完成')
        sock.send(b'ok')

客户端

import os
import socket
import struct
import json

client = socket.socket()

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


BASE_DIR = os.path.dirname(__file__)

while True:
    mode = input('要下载还是上传(1下载 2上传 q退出客户端)>>>:').strip()
    if mode == 'q':
        socket.close()
    if not (mode == '1' or mode == '2'):
        print('没有你输入模式 请重新输入!')
        continue
    # 将模式打包发送给服务端
    client.send(struct.pack('i', len(mode)))
    client.send(mode.encode())
    if mode == '1':
        res = client.recv(4)
        real_num = struct.unpack('i', res)[0]
        info_dict = json.loads(client.recv(real_num))
        for i, v in info_dict.items():
            print(f'文件编号:{i}  --文件名:{v}')
        input_id = input('输入要下载的编号>>>:').strip()
        if input_id not in info_dict:
            print('输入编号不合法!')
            continue
        # 打包发送给服务端
        c_hard = struct.pack('i', len(input_id))
        client.send(c_hard)
        client.send(input_id.encode())
        # 接受真实文件数据字典获取文件大小
        real_db_dict = json.loads(client.recv(struct.unpack('i', client.recv(4))[0]).decode('utf8'))
        size = real_db_dict.get('file_size')
        name = real_db_dict.get('file_name')
        # 获取真正文件
        # real_file = client.recv(size)
        w_size = 0
        with open(os.path.join(BASE_DIR, name), 'wb') as f:
            while w_size < size:
                real_file = client.recv(1024)
                f.write(real_file)
                w_size += len(real_file)
            print('下载成功')
    else:
        while True:
            to_path = input('请输入你当前计算机要发送文件的绝对路径>>>:').strip()
            if not os.path.exists(to_path):
                print('输入路径不存在,请重新输入')
                continue
            file_dict = {
                'c_file_name': to_path,
                'c_file_size': os.path.getsize(to_path)
            }
            print(file_dict)
            # 发送报头
            to = json.dumps(file_dict).encode()
            c_hard = struct.pack('i', len(to))
            client.send(c_hard)
            client.send(to)
            with open(to_path, 'rb') as f:
                for i in f:
                    client.send(i)
            client.recv(2)
            print('数据上传成功')
            break

四 UDP协议

服务端

import socket

while True:
    server = socket.socket(type=socket.SOCK_DGRAM)

    server.bind(('127.0.0.1', 8080))

    data, addr = server.recvfrom(1024)
    print(f"来自{addr}的消息:{data.decode('utf8')}")

    msg = input(f'向{addr}回复消息>>>:').strip()

    server.sendto(msg.encode('utf8'), addr)

客户端

import socket

ADDR = ('127.0.0.1', 8080)
while True:
    clint = socket.socket(type=socket.SOCK_DGRAM)

    msg = input(f'输入向{ADDR}发送的消息>>>:').strip()

    clint.sendto(msg.encode('utf8'), ADDR)

    data, addr = clint.recvfrom(1024)
    print(f"来自{addr}的消息:{data.decode('utf8')}")

五 操作系统的发展史

  1. 穿孔卡片
    CPU利用率非常的低
    好处是程序员可以一个人独占计算机 想干嘛就干嘛

  2. 联机批处理系统
    缩短录入数据的时候 让CPU连续工作的时间变长>>>:提升CPU利用率

  3. 脱机批处理系统
    是现代计算机的雏形>>>:提升CPU利用率

六 多道技术

单道技术:所有的程序排队执行 总耗时是所有程序耗时之和
多道技术:计算机利用空闲时间提前准备好一些数据 提高效率 总耗时较短
切换+保存状态
CPU在两种下会切换(去执行其他程序)
1.程序自身进入IO操作(输入输出操作、获取用户输入、time.sleep()、读取文件、保存文件…
2.程序长时间占用CPU
保存状态:每次切换之前要记录下当前执行的状态 之后切回来基于当前状态继续执行

你可能感兴趣的:(网络,tcp/ip,服务器)