socket:Python网络通信套接字

news/2024/10/6 6:43:47

Socket网络通信套接字

socket库提供了一个底层C API,可以使用BSD套接字接口实现网络通信。它包括socket类,用于处理具体的数据通道,还包括用来完成网络相关任务的函数,如将一个服务器名转换为一个地址以及格式化数据以便在网络上发送。

什么是套接字?

套接字是程序在本地或者通过互联网来回传递数据时所用通信通道的一个端点。

套接字有2个主要属性用于控制如何发送数据:地址簇(address family)控制所用的OSI网络层协议;套接字类型(socket type)控制传输层协议。(参考《计算机网络》7层协议)

地址簇

Python支持3个地址簇:

  • AF_INET:用于IPv4寻址。IPv4长度为4个字节,通常表示为4个数的序列,每个字节对应一个数,用点号分割(如121.63.0.243)。这些值通常被称为IP地址。目前IPv4依旧还是主流。
  • AF_INET6:用于IPv6寻址。目前IPv6已经小范围应用,它支持128位地址和通信流调整,还支持IPv4不支持的一些路由特性。
  • AF_UNIX:用于UNIX域套接字(UDS)的地址簇,这是一种POSIX兼容系统上的进程间通信协议。UDS的实现通常允许操作系统直接从进程向进程间传递数据,而不用通过网络栈。这比使用AF_INET更高效,但是由于要用到文件系统作为寻址的命令空间,所以UDS仅限于同一个系统上的进程。

套接字类型

套接字类型有两种:

  • SOCK_DGRAM:面向消息的数据报传输,数据报套接字通常与UDP关联,即用户数据报协议。这些套接字能提供不可靠的消息传送。
  • SOCK_STREAM:面向流的传输,与TCP相关,即传输控制协议。它们可以在客户和服务器之间提供字节流,通过超时管理,重传和其他特性确保提供消息传送或失败通知。

大多数应用协议(如HTTP)都建立在TCP基础上,因为这样更容易创建自动处理消息排序和传送的复杂应用。

UDP通常用于顺序不太重要的协议(如DNS交换)。UDP与TCP都支持IPv4与IPv6。

套接字的简单应用

gethostbyname_ex()与gethostbyname()

socket库包含一些与网络上的域名服务交互的函数,比如解析域名为IP地址可以用到gethostbyname_ex(),示例如下:

import sockethost_str = ['www.baidu.com','cloud.tencent.com','www.csdn.net'
]
for host in host_str:try:name, aliases, addresses = socket.gethostbyname_ex(host)print(host)print("主机名:", name)print("所有别名:", aliases)print("所有可用IP地址:", addresses)except socket.error as msg:print(host, msg)

运行之后,效果如下:


gethostbyname_ex:该函数返回3个参数,主机名,别名,以及解析能跳转到当前主机的IP地址。

gethostbyname:类似的函数,只返回当前主机的IP地址。

getservbyname()与getservbyport()

socket库提供getservbyname()函数用于查找网络服务的端口号和标准名,示例如下所示:

import socket
from urllib.parse import urlparseurl_str = ['https://www.baidu.com','https://www.csdn.net','smtp://smtp.qq.com',
]
for url in url_str:try:parsed_url = urlparse(url)port = socket.getservbyname(parsed_url.scheme)print(url)print("端口号:", port)except socket.error as msg:print(url, msg)

运行之后,效果如下:

当然,其实最有用的并不是给定一个链接去查询端口号,而是逆向操作。(因为标准化服务端口号一般都是固定的)

socket库提供getservbyport()函数用于完成逆向的服务端口查找,示例代码如下所示:

import socketurl = '{}://smtp.qq.com'.format(socket.getservbyport(25))
print(url)

运行之后,效果如下:

getprotobyname()

socket库还可以使用getprotobyname()函数获取分配给一个传输协议的端口号,示例如下:

import socket#获取匹配开头字符串的所有属性值
def getConstants(prefix):return {getattr(socket, n): nfor n in dir(socket)if n.startswith(prefix)}
ipproto_str = getConstants("IPPROTO_")
for agree in ['tcp', 'udp']:num = socket.getprotobyname(agree)name = ipproto_str[num]print(name, num)

运行之后,效果如下:

对于协议码,在程序定义中一般都是标准化常量,这就是意味着,它们的常量名都有一定的规律,而socket协议码前缀是IPPROTO_。

getaddrinfo(查找服务器地址)

getaddrinfo()函数用于将一个服务的基本地址转换为一个元组列表,其中包含建立一个连接所需要的全部信息。比如其网络簇与协议等,示例如下:

import socket# 获取匹配开头字符串的所有属性值
def getConstants(prefix):return {getattr(socket, n): nfor n in dir(socket)if n.startswith(prefix)}
ipproto_str = getConstants("IPPROTO_")
family_str = getConstants("AF_")
type_str = getConstants("SOCK_")
for response in socket.getaddrinfo('www.csdn.net', 'http', family=socket.AF_INET, type=socket.SOCK_STREAM,proto=socket.IPPROTO_TCP, flags=socket.AI_CANONNAME):family, socktype, ipproto, canonname, sockaddr = responseprint("地址簇:       ", family_str[family])print("套接字类型:    ", type_str[socktype])print("协议码:       ", ipproto_str[ipproto])print("主机规范名:    ", canonname)print("ip地址与端口号:", sockaddr)

运行之后,效果如下:


这里如果只用socket.getaddrinfo(‘www.csdn.net’, ‘http’),表示不需要过滤任何连接信息,但大型的网站一般都有几个IP或者域名跳转到主页的。

所以通过后面的参数,可以筛选自己需要的链接信息。

其中,最后一个参数socket.AI_CANONNAME表示如果主机有别名,那么结果中会包含服务器的标准名。所有没有这个标志,标准名为空。

IP地址的表示方式

如果读者有C的经验,那么肯定知道,通过C语言编写的套接字程序是使用struct sockaddr结构体,它将IP地址表示为二进制,而不是上面显示的Python字符串形式。

如果想在Python和C之间转换IPv4地址,可以使用inet_aton()和inet_ntoa()。示例如下:

import socket
import binasciiip_list = ["192.168.50.1","127.0.0.1"
]
for ip in ip_list:packed = socket.inet_aton(ip)print("原始字符串ip地址:", ip)print("C库能识别的ip地址", binascii.hexlify(packed))print("还原C库ip地址字符串", socket.inet_ntoa(packed))print()

运行之后,效果如下:

inet_pton()与inet_ntop()

相信读者如果在测试上面代码,那么输入上面inet_aton()函数时,一定看到提醒中还有inet_pton()与inet_ntop()函数。

这2个函数既能处理IPv4也能处理IPv6,而inet_aton()和inet_ntoa()只能处理IPv4。它们的使用方式如下:

import socket
import binasciiipv6_str = "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b"
packed = socket.inet_pton(socket.AF_INET6, ipv6_str)
print("原始字符串ip地址:", ipv6_str)
print("C库能识别的ip地址", binascii.hexlify(packed))
print("还原C库ip地址字符串", socket.inet_ntop(socket.AF_INET6, packed))
print()ipv4_str = "192.168.50.1"
packed = socket.inet_pton(socket.AF_INET, ipv4_str)
print("原始字符串ip地址:", ipv4_str)
print("C库能识别的ip地址", binascii.hexlify(packed))
print("还原C库ip地址字符串", socket.inet_ntop(socket.AF_INET, packed))
print()

运行之后,效果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/28527.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

el-upload以及blob自动根据列表名称匹配下载

dom文档<el-row :gutter="20"><el-col :span="16" :offset="0"><el-form-item label-width="120px" label="文件上传"><el-uploadref="upload"class="upload-file-uploader upload-dem…

振弦采集仪在岩土工程监测中的故障排除和维护要点

振弦采集仪在岩土工程监测中的故障排除和维护要点 河北稳控科技振弦采集仪在岩土工程监测中是一种常用的测量设备,通过测量振弦的振动频率来判断土体的力学性质和变形情况。然而,如果振弦采集仪出现故障,则会影响监测工作的正常进行。因此,掌握振弦采集仪的故障排除和维护要…

Mysql-事务的基本特性和隔离级别

0.背景 在数据库中,事务是一组数据库操作,可以将事务操作视为一个基本的工作单元。 1.事务的基本特性 事务的基本特性“ACID” 对于事务呢,就是这一组sql操作,要确保ACID这4个基本特性。 哎,八股文不好背,我记忆方式是:一元吃个(原持隔)原子性(Atomicity):事务中的…

使用pycnblog一键拖拽同步markdown和图片

目录原因解决办法参考链接准备工作配置config.yaml其他设置图片运行 原因本地使用Typora写完文档,上传博客园时,图片不能同步解决办法 参考链接博客园上传markdown文件准备工作下载工具pycnblog安装Python3pip install pyyaml配置config.yaml blog_url: https://rpc.cnblogs.…

blazor优雅的方式导入组件相关的js脚本

基本的组件导入方式为:1 await JsRuntime.InvokeVoidAsync("import", $"XXXXX.js");优雅的组件导入方式:1 await JsRuntime.ImportAsync<DocEditor>();这种优雅一点不难,只需要写一个扩展方法,把他放在任意地方并且导入命名空间,或者放到和项目…

02 冒泡排序

02 冒泡排序1.冒泡排序的含义每次交换两个,把大的扔在末尾, 每一轮可以确定末尾是最大的,然后是次尾部,依次进行下去。 老师:每次都是搞定最大的数,最大的数往右边冒。再接着搞定下一轮,直到整个数组有序。 图示:2.示例代码 def bubble_sort(arr):# if not arr or len(…

一站式生活新体验:可视化技术让公寓商场综合楼焕新生

可视化技术将传统的居住与购物空间进行了完美融合。在这里,你不再需要为了购买生活用品而特地跑到远处的商场,也不再需要为了找一家心仪的餐厅而四处奔波。通过可视化技术,你可以轻松查看到楼内的各个商铺、餐厅、健身房等配套设施的分布情况,一键导航直达目的地,享受一站…

MySQL-基础语法教程及事务和索引

基础解析: select 要几列 where要几行,用来对行进行过滤,加where,查出来的行变少 *代表所有的列 增删改查UPDATE SET 更新 UPDATE scores SET score=300 WHERE NAME="王大" AND kemu="语文" delete语法 DELETE FROM scores WHERE ID =11#删除整张表里的…