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
>>> 



待续。。。

你可能感兴趣的:(Python编程)