文章详情

短信预约信息系统项目管理师 报名、考试、查分时间动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Python实现socket库网络通信套接字

2022-06-02 22:30

关注
目录

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个地址簇:

套接字类型

套接字类型有两种:

大多数应用协议(如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()

运行之后,效果如下:

IPV6

以上就是Python实现socket库网络通信套接字的详细内容,更多关于Python socket库的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯