python - 网络
网络基础
- 什么是网络通讯:
使用网络能够把多方链接在一起,然后可以进行数据传递
所谓的网络编程就是,让在不同的电脑上的软件能够进行数据传递,即进程之间的通信
- 网络通讯基本概念:
1、IP地址
用来在网络中标记一台电脑,比如192.168.1.1;在本地局域网上是唯一的。
2、IP地址有五类:
A:1.0.0.1-126.255.255.254 网络地址的最高位必须是“0”,可用的A类网络有126个,每个网络能容纳1677214个主机
B:128.1.0.1-191.255.255.254 网络地址的最高位必须是“10”,可用的B类网络有16384个,每个网络能容纳65534主机
C:192.0.1.1-223.255.255.254 网络地址的最高位必须是“110”C类网络可达2097152个,每个网络能容纳254个主机
D:224.0.0.1-239.255.255.254 D类IP地址第一个字节以“1110”开始,它是一个专门保留的地址。它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中多点广播地址用来一次寻址一组计算机 s 地址范围
E:以“1111”开始,为将来使用保留,E类地址保留,仅作实验和开发用
子网掩码:区分网络号和主机号
3、私有ip:
国际规定有一部分IP地址是用于我们的局域网使用,也就是属于私网IP,不在公网中使用的,(本地局域网上的IP,专门为组织机构内部使用)它们的范围是:
10.0.0.0~10.255.255.255
172.16.0.0~172.31.255.255
192.168.0.0~192.168.255.255
IP地址127.0.0.1~127.255.255.255用于回路测试,
如:127.0.0.1可以代表本机IP地址,用http://127.0.0.1就可以测试本机中配置的Web服务器。
4、ifconfig:
显示所有网卡的信息:(windows中使用ipconfig)
5、ping:
通常用ping来检测网络是否正常
- 端口:(用来标记区分进程)
1、一台拥有IP地址的主机可以提供许多服务,比如HTTP(万维网服务)、FTP(文件传输)、SMTP(电子邮件)等,这些服务完全可以通过1个
IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。实际上是通过“IP地
址+端口号”来区分不同的服务的。 需要注意的是,端口并不是一一对应的。比如你的电脑作为客户机访问一台WWW服务器时,WWW服务器使用“80”端口
与你的电脑通信,但你的电脑则可能使用“3457”这样的端口。
2、端口是通过端口号来标记的,端口号只有整数,范围是从0到65535
3、端口号不是随意使用的,而是按照一定的规定进行分配。知名端口是众所周知的端口号,范围从0到1023;80端口分配给HTTP服务;21端口分配给FTP服务
- 网络传输协议:
udp和tcp都是网络传输的协议,只不过具体传输形式不一样,但功能都是定义网络传输数据规则。
根据TCP/IP协议簇功能的不同,将它分为了几种层次:
网络接口层(链路层) 物理层
网络层 数据链路层
传输层 网络层
应用层 传输层
会话层
表示层
应用层
网络传输三个必要的前置条件:ip地址,协议,端口
Socket-UDP编程-简介
socket:通过网络完成进程间通信的方式
1、Socket本质是编程接口(API): Socket 是对 TCP/IP 协议的封装
套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认
2.创建socket
import socket #导入套接字模块
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
该函数带有两个参数(参数必须写) :AF_INET(ipv4协议于 Internet 进程间通信)
套接字类型: SOCK_STREAM(流式套接字,用于TCP 协议)
SOCK_DGRAM(数据报套接字, 用于 UDP 协议)
确定了IP地址端口号(ipv4协议),TCP或UDP协议之后,计算机之间可以进行通信
3 互联网协议簇
UDP --- User Data Protocol,用户数据报协议
TCP --- Transmission Control Protocol,传输控制协议
4.Socket编程-udp编程
发送数据
from socket import *
s = socket(AF_INET, SOCK_DGRAM) #创建套接字
addr = ('192.168.1.17', 8080) #准备接收方地址
data = input("请输入:")
s.sendto(data.encode(),addr) #发送数据时,python3需要将字符串转成byte #encode(‘utf-8’)# 用utf-8对数据进行编码,获得bytes类型对象 #decode()反过来
s.close()
接收数据
from socket import * s = socket(AF_INET, SOCK_DGRAM) #创建套接字
addr = ('192.168.1.17', 8080) #准备接收方地址
data = input("请输入:")
s.sendto(data.encode(),addr) #等待接收数据
redata = s.recvfrom(1024) #1024表示本次接收的最大字节数
print(redata)
s.close()
5.TFTP(Trivial File Transfer Protocol,简单文件传输协议)
使用这个协议,就可以实现简单文件的下载 tftp端口号为69
- TFTP格式要求
- 构造下载请求数据:“1test.jpg0octet0”
import struct
cmb_buf = struct.pack(“!H8sb5sb”,1,b“test.jpg”,0,b“octet”,0)
!H8sb5sb: ! 表示按照网络传输数据要求的形式来组织数据(占位的格式)
H 表示将后面的 1 替换成占两个字节
8s 相当于8个s(ssssssss)占8个字节
b 占一个字节
- struct模块使用
struct模块可以按照指定格式将Python数据转换为字符串,该字符串为字节流
struct模块中最重要的三个函数是pack(), unpack(), calcsize()
按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流):pack(fmt, v1, v2, ...)
按照给定的格式(fmt)解析字节流string,返回解析出来的元组:unpack(fmt, string)
计算给定的格式(fmt)占用多少字节的内存:calcsize(fmt)
- TFTP下载器
import struct
from socket import *
filename = 'test1.jpg'
server_ip = '192.168.1.3'
send_data = struct.pack('!H%dsb5sb' % len(filename), 1, filename.encode(), 0, 'octet'.encode(), 0)
s = socket(AF_INET, SOCK_DGRAM)
s.sendto(send_data, (server_ip, 69)) # 第一次发送, 连接服务器69端口
f = open(filename, 'ab') #a:以追加模式打开(必要时可以创建)append;b:表示二进制
while True:
recv_data = s.recvfrom(1024) # 接收数据
caozuoma, ack_num = struct.unpack('!HH', recv_data[0][:4]) # 获取数据块编号
rand_port = recv_data[1][1] # 获取服务器的随机端口
if int(caozuoma) == 5:
print('文件不存在...')
break
print("操作码:%d,ACK:%d,服务器随机端口:%d,数据长度:%d"%(caozuoma, ack_num, rand_port, len(recv_data[0])))
f.write(recv_data[0][4:])#将数据写入
if len(recv_data[0]) < 516:
break
ack_data = struct.pack("!HH", 4, ack_num)
s.sendto(ack_data, (server_ip, rand_port)) # 回复ACK确认包
udp 广播
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #对这个需要发送广播数据的套接字进行修改设置,否则不能发送广播数据
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #允许s发送广播数据
代码实现广播
import socket
dest = (‘
#创建udp套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#对这个需要发送广播数据的套接字进行修改设置,否则不能发送广播数据
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #允许s发送广播数据
#setsocketopt 设置套接字选项
#以广播形式发送数据到本网络的所有电脑中
s.sendto(b'Hi',dest)
print("等待回复")
while True:
(buf, address) = s.recvfrom(2048)
print(address,buf.decode(“GB2312”))
Socket-tcp编程-简介
1.TCP:传输控制协议
TCP通信模型: 在通信之前,必须先等待建立链接
2 . 三次握手
3. 四次挥手
TCP服务器
from socket import *
tcpSerSocket = socket(AF_INET, SOCK_STREAM)
address = ("", 7788)
tcpSerSocket.bind(address)
tcpSerSocket.listen(5)#设置最大连接数
newSocket, clientAddr = tcpSerSocket.accept()
# 如果有新的客户端来链接服务器, 那么就产创建个新的套接字
# newSocket来为这个客户端服务
# tcpSerSocket就可以省下来等待其他新客户端的链接
recvData = newSocket.recv(1024)# 接收对方发送过来的数据, 最大接收1024个字节
newSocket.send("thank you!")
newSocket.close()
tcpSerSocket.close()
TCP客户端
from socket import *
clientSocket = socket(AF_INET, SOCK_STREAM)
serAddr = ('192.168.1.17', 7788)#链接服务器
clientSocket.connect(serAddr)
clientSocket.send(b"hello")
recvData = clientSocket.recv(1024)
print("接收到的数据为:", recvData)
clientSocket.close()
并发网络服务器
from socket import *
from multiprocessing import *
from time import sleep
def dealWithClient(newSocket,destAddr):
while True:
recvData = newSocket.recv(1024)
if len(recvData)>0:
print(recvData)
else:
print("客户端关闭")
break
newSocket.close()
def main():
serSocket = socket(AF_INET,SOCK_STREAM)
serSocket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
localAddr = ("",7788)
serSocket.bind(localAddr)
serSocket.listen(5)
try:
while True:
print("主进程等待连接")
newSocket,destAddr = serSocket.accept()
client = Process(target=dealWithClient,args=(newSocket,destAddr))
client.start()
newSocket.close()
finally:
serSocket.close()
if __name__ == "__main__":
main()