zoukankan      html  css  js  c++  java
  • python网络编程应用(一)

       在之前的一篇博客《python网络编程基础中介绍了socket.socket()函数及其应用,其实socket模块中还有很多属性可供网络应用程序使用。这里将详细讲解一下socket模块中一些常用到的函数/属性。

      1. socket模块属性

      下面列出了一些常用的socket模块属性。(引用自《python核心编程》)

     

      更详细的函数说明,请看python官方文档中的socket模块:https://docs.python.org/2/library/socket.html

       2. 实际应用中的实例分析

      2.1 打印设备名和IPV4地址

      函数原型: socket.gethostname() 和 socket.gethostbyname(hostname) 。也可以使用socket.getfqdn() 返回完整的域名字。

    host_name = socket.gethostname()     # 获取设备名
    
    ip_addr = socket.gethostbyname(host_name)  # 获取本机IP
    
    remote_host = 'www.python.org'
    ip_addr = socket.gethostbyname(remote_host)  # 获取远程主机的IP

      2.2 打印本地网络接口的IPV4地址 

    import socket, fcntl, struct
    
    ifname = "eth0"
    
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    inet = fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))
    ret = socket.inet_ntoa(inet[20:24])
    print ret

       2.3 IPV4地址格式转换

      函数原型:socket.inet_aton(ip_string 和socket.inet_ntoa(packed_ip) 。  如果需要ipv6支持,就需要使用inet_pton()/inet_ntop()函数。

    from binascii import hexlify  # 以十六进制形式表示二进制数据
    
    ip_addr = '192.168.1.15'
    packed_ip_addr = socket.inet_aton(ip_addr)  # 将字符串形式的IP地址转换成32位二进制格式
    unpacked_ip_addr = socket.inet_ntoa(packed_ip_addr) # 与上面相反
    print "IP Address: %s" % ip_addr 
    print "Packed: %s" % hexlify(packed_ip_addr)
    print "Unpacked: %s" % unpacked_ip_addr

      2.4 通过指定端口和协议找服务名

      函数原型: socket.getservbyname(servicename[, protocolname])  和  socket.getservbyport(port[, protocolname]) 。协议名可以省略,默认是找所有的协议,如需指定,只能是‘tcp’或者‘udp’。                   

    serverport = socket.getservbyname('http','tcp')
    servername = socket.getservbyport(80,'tcp')
    

      2.5 主机字节序与网络字节序之间的转换 

    data = 1234
    
    # 32-bit
    print "Original: %s => Long host byte: %s => Network byte: %s" % (data,socket.ntohl(data),socket.htonl(data)
    # 16-bit
    print "Original: %s => Short host byte: %s => Network byte: %s" % (data,socket.ntohs(data),socket.htons(data)
    ## 函数名中的n表示网络; h表示主机; l表示长整型; s表示短整型,即16位。 

      2.6 设置套接字超时

    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.settimeout(100)
    print s.gettimeout()

      2.7 设置缓冲区大小

      setsockopt()方法接收三个参数:level、optname和value。其中,optname是选项名,value是该选项名的值。value所用的符号常量(SO_*等)可以在socket模块中查看。

    import socket 
    
    s_buf = 1024
    r_buf = 1024
    
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    bufsize = sock.getsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF)
    print "bufsize [Before]: %d" % bufsize
    
    sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF,s_buf)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF,r_buf)
    bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
    print "bufsize [After]: %d" % bufsize
    

      2.8 设置套接字(非)阻塞模式

      默认情况下,TCP套接字是处于阻塞模式下的。这种模式会使操作效率低下,如果两个程序最后都在等待对方发送或者接收数据,就有可能导致死锁。调用setblocking()方法可以改变套接字的阻塞标志。默认值为1,表示会阻塞。传入值为0时则关闭阻塞。如果套接字为非阻塞,并且没有为处理操作做好准备,就会产生一个socket.error。解决的方法是设置一个超时值。

    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.setblocking(1)
    s.settimeout(0.5)
    s.bind(('127.0.0.1',0))
    socket_addr = s.getsockname()
    print str(socket_addr)
    while 1:
      s.listen(1) 

     2.9 地址重用

      当连接有意或无意关闭后,如果想再在这个端口上运行套接字服务端就会抛出一个"Address alreadly in use"异常。解决的方法是启用套接字重用选项SO_REUSEADDR。

    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
     s.bind((bind_ip, bind_port))
     s.listen(5)
        ...

      2.10 处理套接字错误

      在socket套接字使用过程中,很可能会出现很多错误,可以使用try-except语句处理异常。

    # First try-except block
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    except socket.error, e:
        print "Error creating socket: %s" % e
    
    # Second try-except block
    try:
        s.connect((host, port))
    except socket.gaierror, e:
        print "Address-related error connecting to server: %s" % e
        sys.exit(1)
    except socket.error, e:
        print "Connection error: %s" % e
        sys.exit(1)
    
    # Third try-except block
    try:
        s.sendall("GET %s HTTP/1.0
    
    " % filename)
    except socket.error, e:
        print "Error sending data: %s" % e
        sys.exit(1)
    
    while 1:
        # Fourth try-except block
        try:
            buf = s.recv(1024)
        except socket.error, e:
            print "Error receiving data: %s" % e
            sys.exit(1)

      

  • 相关阅读:
    (转)Shell中read的用法详解
    How to install OpenResty
    MYSQL随机抽取查询 MySQL Order By Rand()效率问题
    NGINX、PHP-FPM开机自动启动
    Nginx和PHP-FPM的启动/重启脚本 [转发]
    绕过 <?PHP exit('Access Denied'); ?> 限制
    OpenResty(Nginx)+Lua+GraphicsMagick实现缩略图功能
    ImageMagick资料
    MySQL5.5 RPM安装的默认安装路径
    PHP编译支持mysqli
  • 原文地址:https://www.cnblogs.com/lingerhk/p/4472732.html
Copyright © 2011-2022 走看看