Python实现socket库网络通信套接字
作者:一天一篇Python库 发布时间:2023-08-07 17:38:59
Socket 套接字:通讯端点 简介
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。
Socket 是任何一种计算机网络通讯中最基础的内容。Socket通讯一般用户C/S结构系统的网络通讯。
Socket 网络通讯是基于TCP(传输控制协议)或UDP(用户数据报协议)两种协议通讯,所以有 面向连接(TCP )与无连接(UDP ) 两种通讯方式。
Python 要创建TCP 套接字就得在创建的时候,指定套接字类型为SOCK_STREAM,它使用 TCP/IP通讯协议。
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 socket
host_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 urlparse
url_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 socket
url = '{}://smtp.qq.com'.format(socket.getservbyport(25))
print(url)
运行之后,效果如下:
getprotobyname()
socket库还可以使用getprotobyname()函数获取分配给一个传输协议的端口号,示例如下:
import socket
#获取匹配开头字符串的所有属性值
def getConstants(prefix):
return {
getattr(socket, n): n
for 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): n
for 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 = response
print("地址簇: ", 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 binascii
ip_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 binascii
ipv6_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()
运行之后,效果如下:
来源:https://blog.csdn.net/liyuanjinglyj/article/details/117389370


猜你喜欢
- 本文实例讲述了Python 类,property属性(简化属性的操作),@property,property()用法。分享给大家供大家参考,
- 方法一:同步操作1.pipelines.py文件(处理数据的python文件)import pymysqlclass LvyouPipeli
- 将音频文件拷贝到程序所在目录即可。如下所示:#!/usr/bin/env python# encoding: utf-8"&quo
- 前言在遇到三维数据时,三维图像能给我们对数据带来更加深入地理解。python的matplotlib库就包含了丰富的三维绘图工具。1.创建三维
- 目录正文开始1. DRF 中的限流2. 限流进阶配置3. 限流思路分析4. 源码分析5. 其它注意事项参考资料正文开始先说一个限流这个概念,
- 本文实例讲述了Python socket实现的文件下载器功能。分享给大家供大家参考,具体如下:文件下载器先写客户端再写服务端1.tcp下载器
- 但凡有些事情重复时,我就在想怎么可以用程序来自动化。这里想分享如何每天给女友定时微信发送”晚安“,如果只是晚安,就略显单调,于是爬取金山词霸
- 引言:在微信小程序里,比如商品展示页面的商品详情会有图片展示,PC端设置的商品详情是PC端的宽度,所以在小程序里图片会显示不全,这时就应该做
- 对于很多开发者来说,Navicat这个软件并不陌生, 相信这个彩虹色图标的软件,有效的帮助了你的开发工作。从前上学的时候,我都是用的都是从网
- 这是17年的第一篇博文,话说这天又是产品同学跑过来问我说:hi,lenny,你看现在市面上流行各种装逼H5,随便输入点名字啥的就给我生成房产
- 使用字符串时,常见的操作之一是使用给定的分隔符将字符串拆分为子字符串数组。在本文中,我们将讨论如何在Python中拆分字符串。.split(
- 背景golang版本:1.16之前遇到的问题,docker启动时禁用了oom-kill(kill后服务受损太大),导致golang内存使用接
- 方法一、SELECT SUM(正确数)+SUM(错误数) AS 总记录数,SUM(正确数),SUM(错误数) FROM ( SELECT C
- 1.官网语法pandas.read_csv(filepath_or_buffer, sep=NoDefault.no_default**,*
- 一、中间键的引入:Django中间件(Middleware)是一个 轻量级、底层的 “插件”系 统,可以介入 Django的请求和响应处理过
- 我就废话不多说了,还是直接看代码吧!a = [1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1]b = ['
- 在javascript里怎么样才能把int型转换成string型(1)var x=100 a = &nb
- Python 中有三个非常好用的数据结构,列表,元组和字典, 元组是不可变的,列表可以保存任意类型的Python对象,并可以随意扩展没有大小
- 本文实例讲述了Python决策树之基于信息增益的特征选择。分享给大家供大家参考,具体如下:基于信息增益的特征选取是一种广泛使用在决策树(de
- CURLOPT_RETURNTRANSFER 选项:curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);如