网络编程基础
网络编程基础
一、架构分类:
- C/S架构:client客户端和server服务端
- B/S架构:browser浏览器和server服务端
B/S架构隶属于C/S架构,C/S架构的优势是可以充分的调度PC机的性能,但是B/S架构的优势是统一了接口。
二、网络通信基础
-
局域网与交换机的通信原理
-
ip地址:用来标记电脑用于识别,并且不允许重复。在网络通信中可以在传递信息的时候通过ip地址识别出接收方。
- mac和linux通过命令行终端输入ifconfig来查看ip地址,Windows在命令行中通过ipconfig来查看
- linux中命令行关闭网卡:sudo ifconfig 网卡名 down, 开启网卡:sudo ifconfig 网卡名 up
- ip版本:
- ip v1-v3:实验版本
- ip v4:地址由四组数组成,每组数由逗号隔开,每组数中的最大值是255,最小值为0。ip地址组合的后最大ip地址数量:256256256*256,已经分配完,但是网络需求越来越大。
- ip v5:实验版本
- ip v6:为了解决ip地址不够的问题,但是ip v6普及率还不够。
- ip的组成:192.168.33.xx,由网络号和主机号两部分组成。
- 版本一:前三组标记网络号,后边一组是主机号,网络号相同的情况下主机号绝对不能一样。每一组号码从0-255,理论上这个网络好可以容纳256个主机,但是需要注意的是主机号不能有两个数字不能用:0和255。
- 版本二:前两组为网络号,后两组为主机号,理论上的主机号数量为:256*256=65536
- 版本三:第一组为网络号,后三组为主机号,理论上的主机号数量为:256256256=16777216
具体使用哪种版本根据具体的人数和需求来定。回环地址:127.0.0.1,表示的是本机,不能连接到其他人
-
端口
-
端口号是异种骨特殊的网络通道,端口号只有整数,从0到65535
-
为什么要有端口号:
在网络通信的过程中,通过ip地址来确定信息发送给/接收自拿一台电脑,在接收到信息后电脑需要确定信息应该转给哪个程序来处理,此时ip地址已经不起作用,需要定义端口号来确定 -
端口分类:
- 知名端口:众所周知的端口号,范围从0-1023,80端口分配给HTTP服务,21端口分配给FTP服务。
- 动态端口:可以随便使用的端口号,范围从1024-65535
-
-
网络通信发送消息必须具备的具体内容:
- dest ip:目标ip,用于识别接收信息的电脑
- src ip:源ip,发送信息的电脑ip,即本机,用于目标ip回传信息时识别本机
- dest port: 目标端口号,用于识别哪一个软件来接收并处理信息
- src port: 源端口号,用于识别本机哪一个软件来接收并处理回传的信息
- content: 网络通信中传送信息的内容
三、socket
-
定义:socket(简称:套接字)是进程之间通信的一种方式,也可以理解为插排。它与其他进程间通信的一个区别是:它能实现不同主机间进程的通信,网络上各种各样的软件基本上都是基于socket来实现通信的。
-
创建套接字的基本格式:
- 导入socket:import socket
- 创建套接字:s = socket.socket(AddressFamily, Type)
- AddressFamily
- 用于internet间进程的通信,ipv4必须写成socket.AF_INET
- 用于同一台机器间进程的通信, 必须写成AF_UNIX
- 实际工作中常用AF_INET
- Type:套接字类型,可以使用socket.SOCK_STREAM(流式套接字,主要用于TCP通信)或者socket.SOCK_DGRAM(数据报套接字,主要用于UDP协议)。注意大小写。
- AddressFamily
- 关闭socket对象:s.close()
-
服务端与客户端实现通信:
- server:
- 创建套接字sk
- sk.bind(('ip地址', 端口号))
- 设置监听:conn, addr = sk.accept()
- 接收客户端消息msg_r = conn.recv(接收的字节数).decode('utf-8'),并打印
- 向客户端发送消息:msg_s = types(input('>>>'.encode('utf-8'))),conn.send(msg_s)
- 断开连接:conn.close()
- 关闭套接字:sk.close()
import socket import logging logging.basicConfig( level = logging.DEBUG, format = '%(asctime)s %(filename)s [line: %(lineno)d] %(message)s %(process)d', datefmt = '%a, %b, %d, %Y %H:%M:%S', filename = '../网络基础/server1.log' ) sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.bind(('172.16.12.157', 8003)) sk.listen() conn, addr = sk.accept() while 1: msg_r = conn.recv(1024).decode('utf-8') if msg_r: logging.debug('服务端接收一条消息') if msg_r == 'q': break else: print(msg_r) msg_s = bytes(input('>>>>').encode('utf-8')) conn.send(msg_s) logging.debug('服务端发送一条消息') conn.close() sk.close()
- client:
- 创建套接字
- 建立连接:sk.connect(('ip地址', 端口号))
- 向服务端发送消息:msg_s = types(input('>>>'.encode('utf-8'))),sk.send(msg_s)
- 接收服务端消息msg_r = sk.recv(接收的字节数).decode('utf-8'),并打印
- 关闭套接字:sk.close()
import socket import logging '''创建日志''' logger = logging.getLogger() # 创建日志对象 logger.setLevel(logging.DEBUG) fh = logging.FileHandler('client1.log', encoding='utf-8') sh = logging.StreamHandler() # 创建文件和屏幕句柄 format = logging.Formatter('%(asctime)s %(filename)s [line: %(lineno)d %(message)s %(process)d') sh.setFormatter(format) fh.setFormatter(format) logger.addHandler(sh) logger.addHandler(fh) sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.connect(('172.16.12.157', 8003)) while 1: try: msg_s = input('>>>>') if msg_s == 'q': msg_s = bytes(msg_s.encode('utf-8')) sk.send(msg_s) break else: msg_s = bytes(msg_s.encode('utf-8')) sk.send(msg_s) except ValueError: print('输入格式不正确,请重新输入') msg_s = input('>>>>') finally: logging.debug('客户端发送一条消息') msg_r = sk.recv(1024).decode('utf-8') print(msg_r) if msg_r: logging.debug('客户端接收一条消息') sk.close()
- server:
注意:服务端发送和接收消息都用的是conn,客户端使用的是套接字sk
四、TCP和UDP协议:
-
TCP协议:
- 特征及使用的场景:
- 需要先建立连接,然后才能通信
- 占用连接,可靠性高(消息不会丢失),实时性高,速度慢
- 使用的场景:语音/视频聊天、线下缓存高清视频、qq远程控制、发邮件等
- 建立连接中期间的三次握手:
- 过程:
- 客户端向服务端发送建立连接的请求SYN
- 服务端发送同意ACK,此时客户端向服务端通信的连接已经建立
- 服务端向客户端发送建立连接的请求SYN
- 客户端发送同意ACK
由于服务端向客户端发送的ACK及SYN可以同时发送,所以合并为一条,被成为三次握手。
- 过程:
- 结束连接时的四次挥手:
- 过程:
- 主动端发送断开连接的FIN请求
- 被动端收到请求后发送同意ACK
- 被动端向主动端发送断开连接的FIN请求
- 主动端收到后回复同意ACK,断开连接
- 过程:
- 特征及使用的场景:
为什么建立连接是三次握手,而断开连接却是四次挥手,为什么不能合并为三次挥手:
因为在三次握手的时候还没有传输数据,可以合并,而四次挥手的时候可能还正在传输数据,如果四次挥手合并为三次会造成数据无法发送或者丢失。
- UDP协议
特征及使用的场景:- 不需要建立连接,就可以进行通信
- 不占用连接、传输不可靠(因为网络不稳定的原因可能会造成数据的丢失,丢包)、传输的速度很快
- 使用的场景:在线播放视频、qq/微信发送消息等。