Python 网络编程攻略 第一章

1.1 简介

因为要放上具体的代码,今天就从新浪转战CSDN了

原来对Python有了一定的了解,2和3的差距有时候还是挺折腾人的。原来刷过几个oj,上面都是用Python解决的,对于大部分人来说问题应该不是特别大。

今天开始lz就按照《Python Network Programming Cookbook》这本书来进行追踪,求监督!


ps.第一章还是按照Python3进行代码的,后面的章节,因为有涉及到操作系统的问题,话说我一直不知道为什么Python for Win里面竟然会有os.fork()……后面就直接在Ubuntu 12.04上面实验了。Ubuntu自带Python 2.7,正好和书本当中的版本一样。


1.2 打印设备名和IPv4地址

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"># 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 is %s " %host_name)
    print ("ip address is %s" %ip_address)

if __name__ == '__main__':
    print_machine_info()</span></span></span>
 
__name__注意是两个下划线,表示调用程序的进程名,如果在命令行中运行脚本,__name__的值就是'__main__' 

print函数就是前面格式化,用引号包住,后面一个%,然后再把需要的输出用括号括起来。

1.3 获取远程设备的IP地址

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"># 1_2_remote_machine_info.py

import socket

def get_remote_machine_info():
    remote_host = 'www.python.org'
    try:
        print("IP address: %s" %socket.gethostbyname(remote_host))
    except socket.error as err_msg:
        print("%s %s" %(remote_host, err_msg))

if __name__ == '__main__':
    get_remote_machine_info()</span></span></span>

主机名改变即可,socket.gethostbyname的参数改变。


1.4 将IPv4地址转换成不同的格式

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"># 1_3_ipv4_address_conversion.py

import socket

from binascii import hexlify

def convert_ipv4_address():
    for ip_addr in ['127.0.0.1','192.168.0.1']:
        packed_ip_addr = socket.inet_aton(ip_addr)
        unpacked_ip_addr = socket.inet_ntoa(packed_ip_addr)
        print(" IP address %s  =>  Packed: %s , UnPacked: %s "
              %(ip_addr, hexlify(packed_ip_addr), unpacked_ip_addr))
              
if __name__ == '__main__':
    convert_ipv4_address()</span></span></span>

调用了binascii模块的hexlify函数,以十六进制形式表示二进制数据。


1.5 通过制定的端口和协议找到服务名

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"># 1_4_finding_service_name.py

import socket

def find_service_name():
    protocolname = 'tcp'
    for port in [80,25]:
    #for port in range(20,81):
        print("Port: %s  =>  service name: %s  " %(port, socket.getservbyport(port,protocolname)))
    print("Port: %s  =>  service name: %s " %(53, socket.getservbyport(53, 'udp')))    

if __name__ == '__main__':
    find_service_name()</span></span></span>


1.6 主机字节序和网络字节序之间相互转换

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"># 1_5_integer_conversion.py

import socket

def convert_integer():
    data = 1234
    # 32 bit
    print("original: %s => Long host byte order: %s, Network byte order: %s"
        % (data, socket.ntohl(data), socket.htonl(data)))
    # 16 bit
    print("original: %s => Short host byte order: %s, Network byte order: %s"
        % (data, socket.ntohs(data), socket.htons(data)))
    data1 = socket.htonl(data)
    data2 = socket.ntohl(data1)
    print("%s %s %s" %(data,data1,data2))

if __name__ == '__main__':
    convert_integer()</span></span></span>
 

socket库中的类函数ntohl()把网络字节序转换成了长整形主机字节序。函数名中的n表示网络,h表示主机,l表示长整形,s表示短整型,即16位。

1.7 设定并获取默认的套接字超时时间

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"># 1_6_socket_timeout.py

import socket

def test_socket_timeout():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("Default socket timeout: %s" %s.gettimeout())
    s.settimeout(100)
    print("Current socket timeout: %s" %s.gettimeout())

if __name__ == '__main__':
    test_socket_timeout()
</span></span></span>
需要创建套接字对象。套接字构造方法第一个参数是地址族,第二个参数是套接字类型。

socket=socket.socket(family,type),family的值可以是AF_UNIX(Unix域,用于同一台机器上的进程通讯),也可以是AF_INET(对于IPv4协议的TCP和UDP)。至于type参数,SOCK_STREAM(流套接字)或者SOCK_DGRAM(数据报文套接字),SOCK_RAW(raw套接字)。

gettimeout()方法获取套接字的超时时间,再调用settimeout()方法修改超时时间。传给settimeout()的参数可以是秒数,非负浮点数,也可以是None。如果是None,就禁用了套接字操作的超时检测。

这里提到了socket,那么就说一下socket套接字的用法。

先说一下SNTP服务器,(这样1.14好像没有写的必要了?)这里感谢点击打开链接,写的很详细,大家可以参考。后面还有更加复杂的多线程,后面章节会说明如何编写。

server端:

第一步,创建一个socket对象,参数已经说了,见上。

第二步,socket进行绑定到一个地址上面,进行监听。

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">socket.bind(address)
sock.listen(backlog)</span></span></span>

address是一个(ip,port)的双元素二元组,绑定的时候需要这么操作 socket.bind((ip,port))

backlog表示最多连接数,server收到连接请求之后,这些请求会进行排队,如果队列已经满了,超过backlog数目,那么拒绝请求。

第三步,server通过socket.accept()接收client端来的请求链接。

代码如下,一般会有一个while True的循环,表示服务器一直进行监听。

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">while True:
	client_socket, address = socket.accept()
	data = client_socket.recv(data_payload).decode()
	client_socket.sendall(msg.encode())</span></span></span>
调用accept方法的时候,socket会进入waiting(或阻塞)状态。client端请求链接,建立连接并返回服务器。accept()方法返回一个含有两个元素的双元组,形如client_socket,address。第一个client_socket是新的socket对象,server通过它与client发送信息,address是client的address。

第四步,接收、处理和发送信息。

代码和第三步的代码在一起了。这里需要注意一点,Python3.4有一个捉鸡的问题,上文档

In Python3, bytes strings and unicode strings are now two different types. Since sockets are not aware of string encodings, they are using raw byte strings, that have a slightly different interface from unicode strings.</

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值