网络编程


一.网络基础

​ 1.网络基础相关的知识

​ (1) 架构

​ a. C/S 架构 : client 客户端 和 server 服务器端

​ 优势: 能充分发挥PC机的性能

​ b. B/S 架构 : browser 浏览器 和 server 服务器端

​ 优点 : 统一了应用的接口

​ (2)通信

​ a. 同一台电脑上两个程序通信 : 打开一个文件

​ b. 两个电脑如何通信 : 连一个网线

​ c. 多个电脑通信:

​ ex : 电脑1(源)要找电脑2(目标)

             电脑1首先发送一个请求帧,期中包含(我的ip是192.168.1.1,我的mac地址是xxxxxxxx,我要找ip地址为192.168.1.2的主机),将此请求发送给交换机.

             交换机要广播这条消息给其他所有的主机

             目标主机接收到消息后,对比发现自己就是被找的主机,回复给交换机信息(我的ip地址是192.168.1.2,我的mac地址是yyyyyyyyy,请回复给ip地址为192.168.1.1,mac地址为xxxxxxx的主机)

             交换机单播形式返回给源主机

​ 2.mac地址: 是一个物理地址,全球唯一, 类似于身份证

​ 3.ip地址 : 是一个四位点分十进制,它标识了计算机在网络中的位置

​ 4.交换机的通信方式:

​ 广播: 吼一嗓子

​ 单播 : 一对一

​ 组播 : 一对多

5.arp协议 : 通过目标ip地址获取目标mac地址的一个协议

​ 6.端口 : 操作系统位本机每一运行的程序都随机分配一个端口, 其他电脑上的程序可以通过端口来获取到这个程序 (ip地址 + 端口 能唯一找到某台电脑上的某一个服务程序)(0-65535 0-1023不能用)

​ 7.网段 : 一个局域网内 ip 地址的范围

​ 8.子网掩码 : 用来计算网段的, 子网掩码 & ip 地址 获取网段

​ 9.arp协议 : 同过目标ip地址获取目标mac 地址的一个协议

二.socket模块

一.OSI 五层模型 :

​ 1.应用层 http,https,ftp

​ 2.传输层 四层交换机,四层路由器 UDP和 TCP

​ 3.网络层 路由器,以太网交换机 IP协议

​ 4.数据链路层 交换机,网卡,网桥 arp协议

​ 5.物理层 光纤,集成器,网线

二.socket模块

TCP协议 面向连接,可靠的,面向字节流形式的
UDP协议 无连接的,不可靠,面向数据报形式的,传输速度快
1.交换价和路由器的区别?

​ 交换机的主要功能是组织局域网,经过交换机内部处理解析信息之后,将信息以点对点,点对多的形式,发送给固定端

​ 路由器的主要功能: 进行跨网段进行数据传输,路由选择最佳路径

​ EX:

​ 如果你需要将多台电脑连接到一根网线,用交换机即可

​ 如果你只有一个外网ip, 但是你有好多台电脑需要上网, 用路由器

2.TCP协议编码流程

​ 服务器端: 客户端

实例化对象 实例化对象

绑定ip地址和端口号

监听

接收客户端的连接 连接服务器

收发 收发

关闭 关闭

# 服务端
import socket
import time

sk = socket.socket()
sk.bind(('127.0.0.1', 65534))
sk.listen()
conn, addr = sk.accept()

while 1:

    mag_r = conn.recv(1024).decode('utf-8')
    print(mag_r)
    mag_s = input('>>>')
    conn.send(mag_s.encode('utf-8'))

sk.close()
conn.close()

# 客户端
import socket
import time

sk = socket.socket()
sk.connect(('127.0.0.1', 65534))
while 1:
    mag_r = input('>>>')
    sk.send(mag_r.encode('utf-8'))
    mag_s = sk.recv(1024).decode('utf-8')
    print(mag_s)


sk.close()
3.回环地址: 127.0.0.1 每个计算机都有的这么一个本机地址,只能被本机识别,不会被其他机器识别
4.tcp三次握手: 一定是client先发起请求

​ a. 客户端发起请求连接服务器

​ b.服务器返回 : 接收到请求, 并要求连接客户端

​ c.客户端回复: 可以连接

5.四次挥手: 谁先发起断开连接的请求都可以

​ a. 客户端发起断开连接的请求

​ 意思是: 我想和你断开连接,我没有数据要继续发送,但是如果你有数据需要发送,我可以继续接收

​ b.服务器回复 : 我接收到你的请求了

​ c.服务器发送 : 我已经准备好断开连接了

​ d.客户端回复: 收到你的信息, 断开连接

6.UDP协议

​ type = SOCK_DGRAM

​ UDP协议的通信的优势:

​ 允许一个服务器同时和多个客户端通信, TCP不行

# UDP 服务端
import socket

sk = socket.socket(type=socket.SOCK_DGRAM)

sk.bind(('127.0.0.1', 8880))  # 绑定ip地址和端口
dic = {'alex': '\033[34m', 'wusir': '\033[37m'}  # 配颜色

while 1:
    conn, addr = sk.recvfrom(1024)  # 接收客户端的信息和地址
    mag_r = conn.decode('utf-8')
    name = mag_r.split(':')[0].strip()  
    color = dic.get(name, '')
    print('%s %s \033[0m' % (color, mag_r))
    # print(conn.decode('utf-8'), addr)
    mag_s = input('>>>')
    sk.sendto(mag_s.encode('utf-8'), addr)

    # if conn == '88':
    #     break



sk.close()

# 客户端
# UDP
import socket

sk = socket.socket(type=socket.SOCK_DGRAM)  # 指定UDP协议
name = input('请输入您的名字: ')
while 1:
    mag_s = input('>>>')
    info = name + ' : ' + mag_s
    sk.sendto(info.encode('utf-8'), ('127.0.0.1', 8880))
    conn, addr = sk.recvfrom(1024)
    print(conn.decode('utf-8'), addr)

sk.close()
7.pycharm输出带颜色

​ \033[ 字体颜色: 背景颜色 m 数据 \033[0m

8.自定义编码和解码类继承socket
import socket
# 自定义编码解码类继承socket文件中的socket类

class My_socket(socket.socket):  # 继承自 socket文件中的socket类,此时socket就是父类

    def __init__(self, encoding='utf-8'):
        self.encoding = encoding
        super(My_socket, self).__init__(type=socket.SOCK_DGRAM)  # 执行父类socket中的__init__方法

    def my_sendto(self, mag, addr):
        return self.sendto(mag.encode(self.encoding), addr)  # 调用父类中的init方法

    def my_recvfrom(self, num):
        mag_s, addr = self.recvfrom(num)  # 调用父类中recvfrom方法
        return mag_s.decode(self.encoding), addr
from My_UDP import My_socket
# server端
sk = My_socket()
sk.bind(('127.0.0.1', 8850))

conn, addr = sk.my_recvfrom(1024)

print(conn, addr)
sk.close()
from My_UDP import My_socket
# client端
sk = My_socket()
mag_s = input('>>>')
sk.my_sendto(mag_s, ('127.0.0.1', 8850))

sk.close()

三.执行命令

1.在py代码中如何去调用操作系统的命令

# 服务器端
import socket
import subprocess

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

conn, addr = sk.accept()
while 1:
    mag_r = conn.recv(1024).decode('utf-8')
    r = subprocess.Popen(mag_r, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout = r.stdout.read()
    stderr = r.stderr.read()
    if stderr:
        conn.send(stderr)
    else:
        conn.send(stdout)

conn.close()
sk.close()
# 客户端
# 客户端发送要执行的命令
# 服务器执行, 执行完将结果返回给客户端
# 客户端拿到结果呈现到用户眼前

import socket

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

while 1:
    cmd = input('请输入一个命令>>>')
    sk.send(cmd.encode('utf-8'))

    result = sk.recv(2048).decode('gbk')
    print(result)

sk.close()

2.新模块; subprocess

r = subprocess.Popen(mag_r, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout = r.stdout.read()
stderr = r.stderr.read()

# mag_r    : 代表系统命令
# shell=True    代表这条命令是系统命令,告诉操作系统,将mag_r当做系统命令去执行
# stdout    是执行完系统命令之后,用于保存正确结果的一个管道
# stderr    实执行完系统命令之后,用于保存错误结果的一个管道
print(r.stdout.read().decode('gbk'))
print(r.stderr.read().decode('gbk')) # 操作系统默认编码是gbk

四.粘包问题

1.只有tcp协议才会有粘包,udp不会发生

EX: 发送端发送数据, 接收端不知道应该去如何去接收, 造成的一种数据混乱的现象

2.在tcp协议中有两个机制

​ 1.合包机制(nagle算法) 将多次连续发送且间隔较小的数据, 进行打包成一块数据发送过去

​ 2.拆包机制,在发送端,因为受到网卡的MTU限制, 会将大的超过MTU限制的数据, 拆分成多个小的数据,进行传输, 当传输到目标主机的操作系统层时, 会重新将多个小的数据合并成原本的数据

3.MTU(数据链路层)

​ MTU是Maximum Transmission Unit 的缩写. 意思是网络上传送的最大数据包, MTU的单位是字节, 大部分网络设备的MTU都是1500, 如果本机的MTU比网关的MTU大, 大的数据包就会被拆开来发送,这样会产生很多数据包碎片,增加丢包率,降低网络速度


Author: 二哈君
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source 二哈君 !
 Previous
面试总结 面试总结
1.遍历字典for k,v in dic.items() 2.什么叫闭包?函数内部调用函数外部(局部)的变量 3.在调用一个函数中,如何结束本程序?quit() sys.exit() exit() 让函数抛出异常 4.交换机和路由器的区别?
2020-12-01 二哈君
Next 
python模块 python模块
一.模块初识 模块的分类 内置模块 安装python解释器的时候跟着装上的那些方法 第三方模块 没在安装怕python解释器的时候安装的那些功能 自定义功能 自己写的功能是一个通用的功能,可以当作是一个模块 模块的定义 有的
2020-11-11 二哈君
  TOC