【Python】网络
IP地址
IP地址就是表示网络中设备的一个地址
IP的表现形式
- IPV4 点分十进制形式
- IPV6 冒号十六进制组成
查看IP地址
- Linux使用ifconfig命令
- Windows使用ipconfig命令
查看网络是否能够运行
ping ip
C:\Users\hp>ping baidu.com
正在 Ping baidu.com [110.242.68.66] 具有 32 字节的数据:
来自 110.242.68.66 的回复: 字节=32 时间=20ms TTL=53
来自 110.242.68.66 的回复: 字节=32 时间=29ms TTL=53
来自 110.242.68.66 的回复: 字节=32 时间=21ms TTL=53
来自 110.242.68.66 的回复: 字节=32 时间=21ms TTL=53
110.242.68.66 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 20ms,最长 = 29ms,平均 = 22ms
- 检查本地是否能够通信
ping 127.0.0.1
- 域名 是ip地址的别名
端口
是数据传输的通道,是数据传输的必经之路
分类
一共是65532个端口号
- 知名端口号(0~1023)
- 动态端口号(1024~65532)
ip + 端口号 可以确定唯一的应用成功程序
TCP
概念
是一种面向链接的,可靠的,基于数据流的传输层协议
TCP通信步骤
- 创建连接
- 传输数据
- 关闭连接
TCP的特点
1.面向连接
2.可靠传输
- TCP采用发送应答机制
- 超时重传
- 错误校验
- 流量控制
socket
套接字,是进程之间通信的工具。
TCP客户端程序开发
程序架构:
B/S: (浏览器/服务器)
C/S: (客户端/服务器) 使用某个服务,必须下载对应的客户端软件
客户端开发流程
- 创建对象
- 建立连接
- 发送信息
- 接受信息
- 关闭链接
再python中使用socket,要导入socket模块
1.创建socket对象(socket.socket())
2.建立链接(socket对象.connect())
3.发送信息(socket对象.send())
4.接收信息(socket对象.resv())
5.关闭链接(socket对象.close())
ptyhon中的字符串
python中的字符串分两种类型
str:
byte:字节,二进制,网络传输的基本单位
str-->bytes:str.encode(编码类型)
bytes --> str bytes.decode(编码类型)
gbk 将中文编码成2个字节
utf-8 将中文编码成3个字节
客户端开发代码示例
# 创建对象
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) # 固定写法
# 和服务器建立链接
sock.connect(('127.0.0.1', 8080)) # 元组类型,ip + 端口号
print('链接成功')
# 发送数据
send_message = 'hello'
sock.send(send_message.encode()) # 发送信息
# 接受数据
buffer = sock.recv(1024) # 一次接受多少字节数据 # 如果对方没有发送数据,会出现阻塞式等待
print(buffer.decode())
# 关闭数据
sock.close()
服务器开发
- 创建socket对象
- bind服务器ip + 端口
- listen监听套接字,将注定套接字变为被动套接字,可以接受客户端链接
- 主动套接字:可以接受发送信息的套接字
- 被动套接字:不能收发信息
- accept 阻塞等待客户端的链接
- 有客户端的链接,就会返回一个新的socket,用来和客户端通信
- 新的socket关闭,表示不能通信
- 监听的socket关闭了,不能接受新的客户端链接
特殊情况下:启动服务器的时候,运行一次,马上关闭再次运行,就会出现地址已经被使用了
这个bug,端口需要等待30s-2min才可以再次使用
解决方案:
- 换个端口
- 代码解决,端口复用
listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True) # 端口复用
# 设置级别 设置什么内容(权限) 设置什么值? True
# listen_sock.bind(('127.0.0.1', 8080))
listen_sock.bind(('', 8080)) # 绑定服务器中的任意一个网卡
# 设置监听,参数表示:未accept时,最大的可待连接数
listen_sock.listen(5)
# 等待客户端链接,返回一个元组 socket + (ip + port)
sock, ip_port = listen_sock.accept()
print(f'客户端{ip_port}连接了')
# 接受信息
buff = sock.recv(1024)
print(buff.decode())
# 发送信息
send_message = '信息已接受'
sock.send(send_message.encode())
# 关闭链接
sock.close()
listen_sock.close()
判断客户端断开
使用recv的返回值判断,当对方的sock关闭后,sock就不会阻塞了,recv接受的内容是空字符串,长度为0
buff = sock.recv(1024)
if buff:
print(buff.decode())
else:
print('客户端已关闭')
多路版本的服务器
import socket
import threading
def handle_request(sock, ip_port):
while True:
# 接收信息
buff = sock.recv(1024)
if buff:
print(f'解说的信息是:{buff.decode()}')
send_message = '信息已收到'.encode()
sock.send(send_message)
else:
print(f'客户端{ip_port}已经下线...')
break
sock.close()
if __name__ == '__main__':
listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True)
listen_sock.bind(('', 8080))
listen_sock.listen(5)
print('等待链接中...')
while True:
sock, ip_port = listen_sock.accept()
print(f'客户端{ip_port}已上线。。。')
# 创建线程执行任务
handle = threading.Thread(target=handle_request, args=(sock, ip_port))
handle.start()
listen_sock.close()
'''
等待链接中...
客户端('127.0.0.1', 52784)已上线。。。
解说的信息是:hello
客户端('127.0.0.1', 52784)已经下线...
'''
协程
实现多任务的方式,比线程占用资源更小文章来源:https://www.toymoban.com/news/detail-428781.html
方法
import gevent
# pip install gevent
import gevent
def sing(singer, song):
for i in range(5):
print(f'{singer} is singing {song}')
# gevent遇到阻塞式等待会切换携程
gevent.sleep(0.1) # 切换携程
def dance(dancer, name):
for i in range(5):
print(f'{name} {dancer} is dancing')
gevent.sleep(0.1)
if __name__ == '__main__':
# 创建协程对象
g1 = gevent.spawn(sing, '张三', '阿山')
g2 = gevent.spawn(dance, '花花', '阿山')
# 阻塞式等待
g1.join() # 没有阻塞就不会切换,就会直接结束
g2.join()
'''
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
'''
猴子补丁
gevent不会识别time.sleep(),可以使用猴子补丁的方式 ,将time.sleep()转化为gevent.sleep()文章来源地址https://www.toymoban.com/news/detail-428781.html
import gevent
import time
from gevent import monkey
monkey.patch_all() # 使用gevent中的模块替换系统中的模块
def sing(singer, song):
for i in range(5):
print(f'{singer} is singing {song}')
# gevent遇到阻塞式等待会切换携程
# gevent.sleep(0.1) # 切换携程
time.sleep(0.1)
def dance(dancer, name):
for i in range(5):
print(f'{name} {dancer} is dancing')
# gevent.sleep(0.1)
time.sleep(0.1)
if __name__ == '__main__':
# 创建协程对象
g1 = gevent.spawn(sing, '张三', '阿山')
g2 = gevent.spawn(dance, '花花', '阿山')
# 阻塞式等待
g1.join() # 没有阻塞就不会切换,就会直接结束
g2.join()
'''
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
'''
到了这里,关于【python】网络编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!