从入门到自闭之--网络编程
Posted heyulong1214
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从入门到自闭之--网络编程相关的知识,希望对你有一定的参考价值。
概念:
C/S架构:
- C:client 客户端
- S: server 服务端,为所有的用户提供服务
B/S架构:只要在浏览器输入网址就可以直接使用了
- B:browser 浏览器
- S: server 服务端
B/S更好:更节省资源,不用更新,不依赖环境,
- 统一了所有的web程序入口
C/S架构:安全性,程序比较庞大
mac地址:
? 是一个物理地址,在网卡中存在的,唯一的标识你的网络设备
- mac IP地址:定位到一台机器
- port 端口:0-65535,标识一台机器上的一个服务
- IP+ port 能够唯一标识一台设备
ip地址:
- 是一个逻辑地址
- 是可以根据你的位置变化发生改变的
- 能够在广域网中快速的定位你
- 几个特殊IP
- 127.0.0.1 本地回环地址
- 0.0.0.0 表示你的所有网卡地址,标识本机回环地址+内网地址+公网地址
公网和内网
- 公网ip:你能够在任意一个地方去访问的ip地址(不包含保留字段)
- ip v4:4位点分十进制组成0.0.0.0~255.255.255.255
- IP v6:6位冒分十六进制0:0:0:0:0:0~FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
- 内网:只能在一个区域内使用,除了这个区域就无法使用
- 所有的内网ip都要使用保留字段
- 192.168.0.0--192.168.255.255
- 10.0.0.0-10.255.255.255
- 172.16.0.0-172.31.255.255
路由器和交换机:
交换机:完成局域网内通信
- 通过ip找mac地址:arp协议,只用到广播和单播
- 广播
- 单播
- 组播
路由器:完成局域网间通信(网关)
- 网关:所有与局域网外部通信的时候所过的关口,所有的请求都会在这里换上网关IP对外通信
子网掩码(了解):255.255.255.0
- ip 和子网掩码 按位于运算(0或者1)
- 可以判断要寻找的机器是不是在一个局域网中
端口号:
3306 mysql 数据库 6379 redis端口 5000 flask端口
TCP实时通信
##server
import socket
sk = socket.socket()
sk.bind(("127.0.0.1",9043))
sk.listen()
conn,addr = sk.accept()
conn.send(b‘hi‘)
msg = conn.recv(1024).decode("utf-8")
print(msg)
conn.close()
sk.close()
```Python
##client
import socket
sk = socket.socket()
sk.connect(("127.0.0.1",9043))
msg = sk.recv(1024).decode("utf-8")
print(msg)
sk.send("傻子".encode("utf-8"))
sk.close()
```
网络概念补充:
osi七层协议
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
osi五层协议:
- 应用层
- 传输层 #端口 TCP/UDP
- 网络层 # IP 路由器
- 数据链路层 # mac,arp协议,网卡和交换机
- 物理层
- TCP/IP--网络层arp
TCP:
? 上传,下载,邮件,可靠,面向连接,速度慢,能传递的数据长度不限
两边需要先连接
三次握手
第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。 第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。 第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
消息传递:(主要看发送,连接时的状态)
断开连接
四次挥手
(第一次挥手 当客户端向服务端请求断开,这时会发送fin的标记报文。 第二次挥手 当服务端收到客户端fin断开报文时候,可能正在处理数据,此时服务端会发生ack报文。 第三次挥手 当服务端处理完成后,会再次向客户端发送FIN报文,此时可以断开连接。 第四次挥手 当客户端收到服务端的fin报文,会向服务端发送确认ACK,经过两个msl《Maximum Segment Lifetime》时长后断开连接。)
UDP:
? 即时通讯软件,不可靠,面向数据报,速度快,能传递的数据长度有限
1. 支持一对一,一对多,多对多
粘包:
? 当多条消息发送时接受变成了一条或者出现接收不准确的情况
粘包现象会发生在发送端
- 两条或多条消息间隔时间短,长度短,就会把两条消息在发送之前就拼在一起
- 节省每一次发送消息回复的网络资源
粘包现象会发生在接收端
- 多条消息发送到缓存端,但没有被及时接收,或者接收的长度不足一次发送的长度
- 数据与数据之间没有边界
本质:发送的每一条数据之间没有边界
步骤:
计算要发送的数据字节长度
把字结的长度变成4字节,借助struct
1. 计算要发送的数据字节长度 2. 把字节的长度变成4字节 3. 发送这4个字节 4. 发送数据
- 服务端
1. 客户端:
验证客户端的合法性:
- 客户端:
import socket import hashlib SECRET_KEY = b‘alexbigs‘ def check_client(): randbytes = sk.recv(32) md5 = hashlib.md5(SECRET_KEY) md5.update(randbytes) code = md5.hexdigest().encode(‘utf-8‘) sk.send(code) sk = socket.socket() sk.connect((‘127.0.0.1‘,9001)) check_client() print(‘正常的客户端通信‘)
- 服务端:
import os import socket import hashlib SECRET_KEY = b‘alexbigsb‘ def check_client(conn): randbytes = os.urandom(32) conn.send(randbytes) md5 = hashlib.md5(SECRET_KEY) md5.update(randbytes) code = md5.hexdigest() code_cli = conn.recv(32).decode(‘utf-8‘) return code == code_cli sk = socket.socket() sk.bind((‘127.0.0.1‘,9001)) sk.listen() while True: conn,addr = sk.accept() if not check_client(conn):continue print(‘进程正常的通信了‘) # import os # import hmac # hashlib==hmac # randbytes = os.urandom(32) # mac = hmac.new(SECRET_KEY,randbytes) # ret = mac.digest() # print(ret)
并发的socket
模块socketserver -- 上层模块.
客户端 import socket sk = socket.socket() sk.connect((‘127.0.0.1‘,9001)) while True: ret = sk.recv(1024) print(ret)
import time import socket sk = socket.socket() sk.bind((‘127.0.0.1‘,9001)) sk.listen() while True: conn,addr = sk.accept() n = 0 while True: conn.send(str(n).encode(‘utf-8‘)) n+=1 time.sleep(0.5)
以上是关于从入门到自闭之--网络编程的主要内容,如果未能解决你的问题,请参考以下文章