标签:别人 一个 打电话 ase oca 属性 交互 直接 计算
‘‘‘ 网络通信用于获取一个算法在本地运行所需的数据,还可以共享信息实现分布式处理,另外可以用来管理云服务。 python的标准库提供了一些模块来创建网络服务以及访问现有服务 ipaddress模块提供了一些类来验证、比较和处理IPV4/IPV6网络地址 底层socket库允许直接访问原生C套接字库,可以用于与任何网络服务通信。 selectors提供了一个高层接口,可以同时监视多个套接字,这对于支持网络服务器同时与多个客户通信很有用。select提供了selectors使用的底层API socketserver中的框架抽象了创建一个新的网络服务器所需要的大量重复性工作。 可以结合这些类创建服务器来建立或使用线程以及支持TCP或UDP。应用只需要完成实际的消息处理 ‘‘‘
‘‘‘ ipaddress模块提供了处理IPV4和IPV6网络地址的类。这些类支持验证,查找网络上的地址和主机,以及其他常见操作 ‘‘‘
import binascii
import ipaddress
‘‘‘
最基本的对象表示网络地址本身。可以像ip_address函数传入一个字符串,整数或者字节序列来构造一个地址。
返回值是一个IPv4Address或IPv6Address实例,这取决于使用什么类型的地址
‘‘‘
address = "61.135.169.125"
addr = ipaddress.ip_address(address)
print(addr)
print(f"ip version: {addr.version}")
print(f"is private: {addr.is_private}")
print(f"packed form: {binascii.hexlify(addr.packed)}")
print(f"integer: {int(addr)}")
‘‘‘
61.135.169.125
ip version: 4
is private: False
packed form: b‘3d87a97d‘
integer: 1032300925
‘‘‘
import socket
‘‘‘
socket包含一些与网络上的域名服务交互的函数,这使得程序可以将服务器的主机名转换为数字网路地址。
应用使用地址链接服务器之前并不需要显式地转换地址,不过报告错误时除了报告所用的名字之外,如果还能包含这个数字地址,那么便会很有用
‘‘‘
# 要查找当前主机的正式名,可以使用gethostname函数
print(socket.gethostname()) # WINDOWS-JTP7CGR
# 还可以使用gethostbyname函数根据主机名获取ip地址
print(socket.gethostbyname(socket.gethostname())) # 192.168.0.110
# 不仅如此,还可以根据url,找出网站的ip。
# 总所周知,我们访问百度,可以通过www.baidu.com,但是我们是通过这个域名来访问百度的ip地址,只是ip比较难记罢了
# 我们也可以根据url找到对应网站的ip
print(socket.gethostbyname("www.baidu.com")) # 61.135.169.125
# 如果想访问更多的信息,可以使用这个函数
name, aliases, addressed = socket.gethostbyname_ex("www.baidu.com")
print(name) # www.a.shifen.com
print(aliases) # [‘www.baidu.com‘]
print(addressed) # [‘61.135.169.121‘, ‘61.135.169.125‘]
import socket
‘‘‘
除了ip地址之外,每个套接字地址好包括一个整数端口号。
很多应用可以在同一个主机上运行并监听一个ip地址,不过只有一个套接字可以使用该地址的端口。
通过结合ip地址、协议和端口号,可以唯一地标识一个通信通道,并确保通过一个套接字发送的消息能到达正确的目标
有些端口号已经预先分配给特定的协议。例如,使用SMTP的email服务器使用TCP在端口25完成通信,web客户和服务器使用端口80完成HTTP通信。
‘‘‘
# 可以使用getservbyname方法查找网络服务的端口号和标准名
print(socket.getservbyname("http")) # 80
print(socket.getservbyname("https")) # 443
print(socket.getservbyname("ftp")) # 21
print(socket.getservbyname("smtp")) # 25
# 也可以使用getservbyport根据端口号查找协议
print(socket.getservbyport(80)) # http
print(socket.getservbyport(666)) # doom
import socket
‘‘‘
getaddrinfo函数将一个服务的基本地址转换为一个元组列表,其中包含建立一个连接所需的全部信息。每个元组可能包含不同的网络簇或协议
‘‘‘
res = socket.getaddrinfo("www.baidu.com", "https")
print(res)
# [(<AddressFamily.AF_INET: 2>, 0, 0, ‘‘, (‘61.135.169.125‘, 443)), (<AddressFamily.AF_INET: 2>, 0, 0, ‘‘, (‘61.135.169.121‘, 443))]
import socket
# 创建tcp/ip套接字,这里作为服务端
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定ip和端口,客户端连接这个ip和端口就可以向我们这里的服务端发送消息
# 这里要传入元组
server.bind(("localhost", 8888))
# 同时监听多少个到来的链接,也就是一次最多可以让多少个客户连接
# 虽然可以监听多个链接,但是一次性只能处理一个。
# 比如监听5,表示接收5个链接,当来了5个链接,并不是同时处理5个,而是一次性处理一个,其他的4个要排队。而再来第6个链接连队也不让排了,直接拒绝接收了
server.listen(5)
# 创建循环,表示一个链接关闭了,继续循环处理下一个链接
while True:
# accept:等待客户端的链接,一旦到来,就会与之交互
# 会有两个返回值。conn:客户端与服务端之间建立的一个链接。addr:客户的地址
# 这个过程是会阻塞的
conn, addr = server.accept()
# 创建循环,因为消息不止发送一次,会多次来回发送,你一句我一句,直到没话了,结束循环
# 从而执行外层循环,等待下一个链接,然后继续循环你一句我一句
while True:
# 发送消息和接收消息都是conn这个链接实例去执行的
# recv表示接收数据,1024表示最多一次性最多接收1024个字节
data = conn.recv(1024)
# 如果对方断开链接了,那么发送的数据就为空了
# 所以要进行判断,如果得到的数据为空,那么就break,也就是断开当前的链接
if not data:
print(f"客户端{addr}:断开链接")
break
# 有数据的话,那么打印出来
print(str(data, encoding="utf-8"))
# 同时也给客户端发送数据
conn.sendall(data + bytes(" 我收到了", encoding="utf-8"))
# 清理链接,进行资源、端口的释放等等
conn.close()
import socket
# 我们是客户端,所以要创建一个绑定到指定ip和端口的链接
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 这里不再是bind了,而是connect,因为我们不是创建服务器等待链接,而是客户端,要绑定指定的链接去连接别人
client.connect(("localhost", 8888))
while True:
# 发送数据,到时候服务端也会回数据
client.sendall(bytes(input("你要发送的数据:"), encoding="utf-8"))
data = client.recv(1024)
print(str(data, encoding="utf-8"))


可以看到,这里还有一个不完美的地方,那就是当客户端断开链接时,服务端报错了,这要咋办呢?可以在第二层循环来一个异常捕获就行了
标签:别人 一个 打电话 ase oca 属性 交互 直接 计算
原文地址:https://www.cnblogs.com/traditional/p/10617030.html