python网络编程

一、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 模块(注意是四个_)

Python不同于C/C++,程序执行并不需要主程序,如main(),而是文件自上而下的执行。
但很多Python程序中都有这样的语句

if __name__ == '__main__':
    statements

这段代码的主要作用主要是让该python文件既可以独立运行,也可以当做模块导入到其他文件。当导入到其他的脚本文件的时候,此时__name__的名字其实是导入模块的名字,不是’main’, main代码里面的就不执行了。
比如写一个程序test_main.py:

def fun():
    print 'This is function'
if __name__ == '__main__':
    fun()
    print 'This is main'

此结果为test_main.py顺序执行的结果,然后将test_main作为模块引入

可以发现,'main’模块中的代码并未执行。
因此我们可以把打印本机名及地址的代码整合在一个独立的函数print_machine_info()中,该函数使用内置的套接字类方法。
我们从通常的Python main__块调用我们的函数。 在运行时,Python会将值分配给某些内部变量,例如__name。 在这种情况下,name__指的是调用进程的名称。 从命令行运行此脚本时,如以下命令所示,名称将为__main,但如果从其他脚本导入模块,则名称将不同。 这意味着当从命令行调用模块时,它将自动运行我们的print_machine_info函数; 但是,单独导入时,用户需要显式调用该函数。

1_1_local_machine_info.py 代码如下:
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

例6:设置与获取默认套接字的超时
你可以通过socket实例对象的gettimeout()及settimeout()方法来获取与设置timeout的值。
1_6_socket_timeout.py 代码如下:

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值