一、Sockets, IPv4, and Simple Client/Server Programming
本章通过一些简单的案例介绍Python的核心网络库。 Python的套接字模块具有基于类和基于实例的实用程序。基于类和基于实例的方法之间的区别在于前者不需要套接字对象的实例。 例如,为了打印机器的IP地址,您不需要套接字对象。 相反,您可以只调用套接字的基于类的方法。 另一方面,如果需要将某些数据发送到服务器应用程序,则创建套接字对象以执行该显式操作更为直观。
例1:打印本机名与IP地址:
import socket
host_name = socket.gethostname()
host_ip = socket.gethostbyname(host_name)
print("Host name: ", host_name)
print("IP address:", host_ip)
扩展:__main__ 模块(注意是四个_)
if __name__ == '__main__':
statements
比如写一个程序test_main.py:
def fun():
print 'This is function'
if __name__ == '__main__':
fun()
print 'This is main'
import socket
def print_machine_info():
host_name = socket.gethostname()
ip_address = socket.gethostbyname(host_name)
print ("Host name: ", host_name)
print ("IP address: ",ip_address)
if __name__ == "__main__":
print_machine_info()
运行结果:
>>>
Host name: zhengwork
IP address: 172.16.24.188
>>>
例2:获取远程主机的IP地址
1_2_remote_machine_info.py代码如下:
import socket
def get_remote_machine_info():
remote_host = "www.sina.com"
try:
print ("IP address: ", socket.gethostbyname(remote_host))
except socket.error as err_msg:
print(remote_host,err_msg)
if __name__ == "__main__":
get_remote_machine_info()
运行结果:
>>>
IP address: 61.155.142.250
>>>
例3:IP地址数据格式转换
当您要处理底层网络功能时,有时,通常的点分十进制的IP地址表示法并不是很有用,这时我们就需要将它转换为32位二进制格式。
1_3_ip4_address_conversion.py代码:
import socket
from binascii import hexlify
def convert_ip4_address():
for ip_addr in ['127.0.0.1','192.168.0.100']:
packed_ip_addr = socket.inet_aton (ip_addr) #aton是转换IPV4成为32位打包的二进制格式
unpacked_ip_addr =socket.inet_ntoa(packed_ip_addr) #ntoa 转换32位打包的IPV4为标准的点分十进制
print("IP address :{} => packed: {}".format(ip_addr,hexlify(packed_ip_addr)))
if __name__ == "__main__":
convert_ip4_address()
运行结果:
>>>
IP address :127.0.0.1 => packed: b'7f000001'
IP address :192.168.0.100 => packed: b'c0a80064'
>>>
说明:binascii模块是二进制和ASCII互转以及其他进制转换,hexlify()作用是返回二进制数据的十六进制表示,每一个字节的数据转换成相应的2位十六进制表示。
例4:根据提供的协议名称及端口号,查找服务名称。
如果你知道网络的端口号,我们可以利用getservbyport() 这个socket类的功能来得到。
1_4_finding_service_name.py代码如下:
import socket
def find_service_name():
protocolname = 'tcp'
for port in [80,25,21]:
print("Port: {} => service name: {}".format(port,socket.getservbyport(port,protocolname)))
print("Port: {} => service name: {}".format(53,socket.getservbyport(53,'udp')))
if __name__ == "__main__":
find_service_name()
运行结果如下:
>>>
Port: 80 => service name: http
Port: 25 => service name: smtp
Port: 21 => service name: ftp
Port: 53 => service name: domain
>>>
例5:主机字节序与网络字节序的相互转换
如果你需要编写底层网络应用时,则必然要处理两台计算机之间的底层数据传输,因此我们需要将数据转换到网络相应格式。
1_5_integers_conversion.py代码如下:
import socket
def convert_integer():
data = 1234
# 32-bit
print ("Original: {} => Long host byte order: {},Network byte order: {}"\
.format(data, socket.ntohl(data), socket.htonl(data)))
# 16-bit
print ("Orginal: {} => Short host byte order: {}, Network byte order: {}"\
.format(data, socket.ntohs(data), socket.htons(data)))
if __name__ == "__main__":
convert_integer()
运行结果:
>>>
RESTART: D:/onedriver/OneDrive/python network programming code/ch1/1_5_integer_conversion.py
Original: 1234 => Long host byte order: 3523477504,Network byte order: 3523477504
Orginal: 1234 => Short host byte order: 53764, Network byte order: 53764
>>>
import socket
def test_socket_timeout():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print (" Default socket timeout: {}".format(s.gettimeout()))
s.settimeout(100)
print ("Current socket timeout: {}".format(s.gettimeout()))
if __name__ == "__main__":
test_socket_timeout()
运行结果:
Default socket timeout: None
Current socket timeout: 100.0
>>>
待续。。。