套接字、IPv4和简单的客户端/服务器编程

获取本地本地主机名称及ip

#!/usr/bin/env python

import socket

def print_machine_info():
    host_name = socket.gethostname() # return local hostname
    ip_address = socket.gethostbyname(host_name) # return ip of host_name
    print "Host name: %s" % host_name
    print "IP address: %s" % ip_address

if __name__ == "__main__":
    print_machine_info()

获取远程主机ip

#!/usr/bin/python

import socket

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


if __name__ == '__main__':
    get_remote_machine_info()

转化ip地址格式

inet_aton将ip地址打包为32位二进制格式,hexlify以十六进制表示二进制数据
inet_ntoa将而二进制格式转换为字符串形式

#!/usr/bin/python

import socket
from binascii import hexlify

def convert_ip4_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_ip4_address()

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

getservbyport(port, protocolname)获取服务名

#!/user/bin/python

import socket

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

if __name__ == '__main__':
    find_service_name()

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

ntohl(data)、ntohs(data)把网络字节序转成主机字节序
htonl(data)、htons(data)把主机字节序转成网络字节序

#!/usr/bin/python

import socket

def convert_integer():
    data = 1234
    print "data: %s => host data: %s => network data: %s"\
        % (data, socket.ntohl(data), socket.htonl(data))

    print "data: %s => host data: %s => network data: %s"\
        % (data, socket.ntohs(data), socket.htons(data))


if __name__ == '__main__':
    convert_integer()

设定与获取默认套接字超时时间

gettimeout() 获取套接字超时时间
settimeout() 设置套接字超时时间

#!/usr/bin/python

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

处理套接字错误

argparse模块把命令行参数传入骄傲本以及在脚本中解析命令行参数。
socket.gaierror是地址相关的错误
socket.herror是C API中抛出的异常
socket.timeout套接字超时异常

#!/usr/bin/python

import sys
import socket
import argparse

def main():
    # setup argument parsing
    parser = argparse.ArgumentParser(description='Socket Error Example')
    parser.add_argument('--host', action="store", dest="host", required=False)
    parser.add_argument('--port', action="store", dest="port", type=int, required=False)
    parser.add_argument('--file', action="store", dest="file", required=False)
    given_args = parser.parse_args()
    host = given_args.host
    port = given_args.port
    filename = given_args.file
    print "host:",host
    print "port:",port
    print "file:",filename

    # create socket
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    except socket.error, e:
        print "Error creating socket: %s" % e
        sys.exit(1)
    print "create socket success"

    # connect to host/port
    try:
        s.settimeout(10)
        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 "Error connect to Server: %s" % e
        sys.exit(1)
    print "connect server success"

    # send data
    try:
        s.sendall("GET %s HTTP/1.0\r\n\r\n" % filename)
    except socket.error, e:
        print "Error sending data: %s" % e
        sys.exit(1)


    while 1:
        try:
            buf = s.recv(2048)
        except socket.error, e:
            print "Error reveiving data %s" % e
            sys.exit(1)
        if not len(buf):
            break
        sys.stdout.write(buf)

if __name__ == "__main__":
   main()

修改套接字接收发送缓存区大小

#!/usr/bin/python

import socket

SEND_BUF_SIZE = 4096
RECV_BUF_SIZE = 4096

def modify_buff_size():
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

  bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
  print "Buffer size : %d" % bufsize

  sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
  sock.setsockopt(
            socket.SOL_SOCKET,
            socket.SO_SNDBUF,
            SEND_BUF_SIZE)
  sock.setsockopt(
            socket.SOL_SOCKET,
            socket.SO_RCVBUF,
            RECV_BUF_SIZE)

  bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
  print "Buffer size : %d" % bufsize

if __name__ == '__main__':
  modify_buff_size()

修改套接字的阻塞状态

#!/usr/bin/env python

import socket

def test_socket_block():
    # create socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # set block status 1: block 2: no block
    sock.setblocking(1)
    sock.settimeout(0.5)
    # bind ip\port
    sock.bind(("127.0.0.1", 0))
    socket_address = sock.getsockname()
    print " Server launched on socket: %s" %str(socket_address)
    while(1):
        sock.listen(1)


if __name__ == '__main__':
    test_socket_block()

重用套接字地址

#!/usr/bin/python

import socket

def socket_reuseaddr():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    sock_state = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
    print 'sock state: ', sock_state

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock_state = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
    print 'sock state: ', sock_state

    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind(('', 8082))
    server.listen(1)
    while True:
        try:
            connection, addr = server.accept()
            print 'Connect by %s:%s' %(connection[0], addr[1])
        except KeyboardInterrupt:
            break
        except socket.error, msg:
            print msg

if __name__ == '__main__':
    socket_reuseaddr()

从网络时间服务器获取并打印当前时间

#!/usr/bin/python

import ntplib
from time import ctime

def print_machine_time():
    ntp_client = ntplib.NTPClient()
    response = ntp_client.request('pool.ntp.org')
    print ctime(response.tx_time)

if __name__ == '__main__':
    print_machine_time()

编写简单的SNTP客户端

#!/usr/lib/python

import socket
import sys
import time
import struct

SERVER_HOST = '0.uk.pool.ntp.org'
TIME1970 = 2208988800L

def sntp_client():
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    data = '\x1b' + 47 * '\0'
    client.sendto(data, (SERVER_HOST, 123))
    data, address = client.recvfrom(1024)
    if data:
        print 'Response from' ,address
    t = struct.unpack('!12I', data)[10]
    t -= TIME1970
    print '\t Time=%s' % time.ctime(t)

if __name__ == '__main__':
    sntp_client()

简单的客户端/服务器应用

服务器端:

#!/usr/bin/python

import sys
import socket

def start_server():
    server_host = 'localhost'
    server_port = 8082
    # create socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # bind host and port
    sock.bind((server_host, server_port))
    # set max connect number
    sock.listen(1)
    # deal message
    while True:
        connection, address = sock.accept()
        print 'Server connect by', address
        while True:
            data = connection.recv(1024)
            if not data: break
            print address,'--->',data
            connection.send('Echo=>' + data)
        connection.close

if __name__ == '__main__':
    start_server()

客户端:

#!/usr/bin/python

import socket
import sys

def start_client():
    server_host = '127.0.0.1'
    server_port = 8082
    # default message send to server
    message = ['Hello network world']
    # set host\message
    if len(sys.argv) > 1:
        server_host = sys.argv[1]
        if len(sys.argv) >2:
            message = sys.argv[2]
    # create socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # connect to server
    sock.connect((server_host, server_port))
    # deal message
    for line in message:
        sock.send(line)
        data = sock.recv(1024)
        print 'Client received:', repr(data)
    # close socket
    sock.close()


if __name__ == '__main__':
    start_client()

你可能感兴趣的:(Linux,Python)