python - 网络编程,,★定义由于不同机器上


★定义

由于不同机器上的程序要通信,才产生了网络

技术分享图片

◇C/S架构

server服务端

client客户端

◇B/S架构

broswer浏览端

server客户端

  如:各种小程序和公众号

★通信

◇网线

连接每一台机器的桥梁

◇网卡

每台计算机有全球唯一的mac地址(物理地址)

◇ARP协议

通过IP地址找到对应的MAC地址

◇交换机

多台机器之间通信的问题

◇网关

局域网中的机器想要访问局域网外的机器,需要网关

◇网段

IP地址和子网掩码按位【与运算】

◇IP协议

127.0.0.1 本地回环地址为每一台计算机分配IP地址确定哪些地址在同一个子网络

◇通信协议

TCP协议

  全双工,双方都可以收发信息

  建立通信的过程

  1,建立连接:三次握手

  2,数据传输:长链接

  3,断开连接:四次挥手

UDP协议

是一个简单的传输协议,只把数据发出去,但不能保证它们能到达目的地

◇端口

在计算机上,每一个网络通信的程序,都会开一个端口

端口范围:0-65535

一般情况下我们用:8000之后的端口

◆IP和端口的区别

IP:确定唯一的一台机器

端口:确定唯一的一个程序

★五层模型

◇应用层

  协议:

HTTP协议HTTPS协议花钱,可靠FTP传输协议SMTP协议

◇传输层

选择通信协议

TCPUDP

◇网络层

给上一层的信息加上IP信息

  IP协议

◇数据链路层

给上一层的信息加上MAC地址

  ARP协议

◇物理层

  网线网卡

    传输比特流0101010

★socket模块

只要确定了IP和Port,就能使用socket来与之通信

◇类型

基于文件类型:AF_UNIX基于网络类型:AF_INEF

◇socket实例

基于TCP方式(会黏包)

技术分享图片
 1 import socket 2  3 sk = socket.socket()    # 实例socket对象 4 sk.bind((‘127.0.0.1‘, 8080))    # 绑定ip和端口 5 sk.listen()             # 监听 6  7 conn, addr = sk.accept()    # 建立连接 8 conn.send(b‘hello‘)         # 发送消息 9 res = conn.recv(1024).decode(‘utf-8‘)   # 接收消息10 print(res)11 conn.close()        # 关闭连接12 13 sk.close()      # 关闭socket对象
server.py技术分享图片
1 import socket2 3 sk = socket.socket()    # 创建socket对象4 sk.connect((‘127.0.0.1‘, 8080))     # 创建连接5 6 res = sk.recv(1024).decode(‘utf-8‘)     # 接收信息7 print(res)8 sk.send(b‘ok‘)      # 发送信息9 sk.close()      # 关闭连接
client.py

基于UDP方式(会丢包)

技术分享图片
 1 import socket 2  3 sk = socket.socket(type=socket.SOCK_DGRAM)  # 创建一个基于UDP协议的socket对象 4 sk.bind((‘127.0.0.1‘, 8080))     # 绑定IP和port 5  6 ret, addr = sk.recvfrom(1024)   # 接收消息 并接收一个 addr 7 print(ret.decode(‘utf-8‘)) 8 sk.sendto(b‘hello‘,addr)        # 发送消息 需要传addr 9 10 sk.close()      # 关闭socket对象
server.py技术分享图片
 1 import socket 2  3 sk = socket.socket(type=socket.SOCK_DGRAM)  # 创建一个基于UDP协议的socket对象 4 addr = (‘127.0.0.1‘, 8080) 5  6 sk.sendto(b‘hi‘, addr) 7 ret,addr = sk.recvfrom(1024)        # 接收消息 并接收一个 addr 8 print(ret.decode(‘utf-8‘))          # 发送消息 需要传addr 9 10 sk.close()      # 关闭socket对象
client.py

◇黏包(只在TCP协议中)

原因:面向连接的流传输,数据是无边界的

  1,缓冲机制:不知道客户端发送的数据的长度,recv接收不完的数据,会缓存在内存里,等待下一个recv

  2,优化算法:连续的小数据包会被合并在一起发送,会被一个recv接收

解决办法

发送大的数据前,告诉接收端我要传多大的数据,接收端接收合适的数据大小

通过struct模块

  固定长度的bytes

  pack:就是即将把一个数据转换成固定长度的bytes类型

  unpack:unpack之后拿到的数据是一个元祖

技术分享图片
 1 import socket 2 import struct 3  4 sk = socket.socket() 5 sk.bind((‘127.0.0.1‘, 8090)) 6 sk.listen() 7  8 conn, addr = sk.accept() 9 while True:10     cmd = input(‘>>>‘)11     if cmd == ‘q‘:12         break13     conn.send(cmd.encode(‘gbk‘))       # 发命令14     num = conn.recv(4)15     num = struct.unpack(‘i‘, num)[0]    # unpack之后拿到的数据是一个元祖16     ret = conn.recv(num).decode(‘gbk‘)      # 接收信息17     print(ret)18 19 20 conn.close()21 sk.close()
server.py技术分享图片
 1 import socket 2 import subprocess 3 import struct 4  5 sk = socket.socket() 6 sk.connect((‘127.0.0.1‘, 8090)) 7  8 while True: 9     cmd = sk.recv(1024).decode(‘gbk‘)   # 接收一个命令10     if cmd == ‘q‘:11         break12     res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 在本地执行命令13     stdout_ret = res.stdout.read()  # gbk字节14     stderr_ret = res.stderr.read()  # gbk字节15     num = len(stdout_ret) + len(stderr_ret)16     sk.send(struct.pack(‘i‘, num))      # 把数据包的大小传过去(这个数据包本身4字节)17     sk.send(stdout_ret)     # 将命令结果发给服务端18     sk.send(stderr_ret)     # 将命令结果发给服务端19 20 sk.close()
client.py

python - 网络编程

评论关闭