python 网络编程第一章

来源:互联网 发布:python网络爬虫抓取pdf 编辑:程序博客网 时间:2024/06/05 03:01
/**TCP 1.socket()创建套接字-绑定端口  2.bind()让套接字处于监听状态-等待连接 3.listen() 4.accept() 一直阻塞 等待客户端连接 5.recv() 6.send() 7.关闭连接 close(recv),close(sock) */        

//------------------------    /**TCP 1.socket()  创建套接字 2.connect() 发起连接 3.send()    数据请求(发送) 4.recv()    数据应答 5.close() */    
#!/usr/bin/env python#--coding:utf8--import socket,sys,os,argparsefrom binascii import hexlifydef 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("packed_ip_addr:%s"%packed_ip_addr)        # print("unpacked_ip_addr:%s"%unpacked_ip_addr)        print "IP Address: %s => Packed: %s, Unpacked: %s"\              %(ip_addr, hexlify(packed_ip_addr), unpacked_ip_addr)'''socket.getservbyport()'''def find_service_name():    protocolname = 'tcp'    for port in [80, 25]:        print "Port: %s => service name: %s" %(port, socket.getservbyport(port,protocolname))    print "Port: %s => service name: %s" %(53, socket.getservbyport(53, 'udp'))'''socket.ntohl() and socket.htonl()socket.ntohl()把网络字节序转换成了长整形主机字节序。函数名中的n表示网络;h表示主机;l表示长整形;s表示短整形,即16位。'''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))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()def socker_err(host,port,filename):    # setup argument parsing    # parser = argparse.ArgumentParser(description='Socket Error Examples')    # 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    # First try-except block -- create socket    try:        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        # Get the size of the socket's send buffer        bufsize = s.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)        print "Buffer size [Before]:%d" %bufsize    except socket.error, e:        print "Error creating socket: %s" % e        sys.exit(1)    # Second try-except block -- connect to given host/port    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 -- sending 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:        # Fourth tr-except block -- waiting to receive data from remote host        try:            buf = s.recv(2048)        except socket.error, e:            print "Error receiving data: %s" % e            sys.exit(1)        if not len(buf):            break        # write the received data        sys.stdout.write(buf)'''修改接收和发送缓冲区大小在套接字对象上可调用方法getsockopt()和setsockopt()分别获取和修改套接字对象的属性。setsockopt()方法接收三个参数:level、optname和value。其中,optname是选项名,value是该选项的值。第一个参数所用的符号常量(SO_*等)可在socket模块中查看。'''SEND_BUF_SIZE = 4096RECV_BUF_SIZE = 4096def modify_buff():    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    bufsize = s.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)    print "Buffer size [Before]:%d" %bufsize    s.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)    s.setsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF,SEND_BUF_SIZE)    s.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF, RECV_BUF_SIZE)    bufsize = s.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)    print "Buffer size [After]:%d" %bufsize'''在Python中,套接字可以被设置为阻塞模式或者非阻塞模式。在非阻塞模式中,调用API后,例如send()或recv()方法,如果遇到问题就会抛出异常。但在阻塞模式中,遇到错误并不会阻止操作。我们可以创建一个普通的TCP套接字,分别在阻塞模式和非阻塞模式中执行操作实验。为了能在阻塞模式中处理套接字,首先要创建一个套接字对象。然后,调用setblocking(1)把套接字设为阻塞模式,或者调用setblocking(0)把套接字设为非阻塞模式。最后,把套接字绑定到指定的端口上,监听进入的连接。'''def test_socket_modes():    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    s.setblocking(1)    s.settimeout(0.5)    s.bind(('127.0.0.1',0))    socket_address = s.getsockname()    print "Trivial Server launched on socket: %s" %str(socket_address)    while(1):        s.listen(1)'''重用套接字地址创建套接字对象之后,我们可以查询地址重用的状态,比如说旧状态。然后,调用setsockopt()方法,修改地址重用状态的值。再按照常规的步骤,把套接字绑定到一个地址上,监听进入的客户端连接。在这个例子中,我们要捕获KeyboardInterrupt异常,这样按下Ctrl+C键后,Python脚本会终止运行,但不会显示任何异常消息。---你可以在一个终端窗口运行这个脚本,然后在另一个终端窗口中输入telnet localhost8080,尝试连接这个服务器。关闭服务器程序后,还可以使用同一个端口再次连接。然而,如果你把设定SO_REUSEADDR的那行代码注释掉,服务器将不会再次运行脚本。'''def reuse_socket_addr():    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    # Get the old state of the SO_REUSEADDR option    old_state = s.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR)    print "Old sock state: %s" %old_state    # Enable the SO_REUSEADDR option    s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )    new_state = s.getsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR )    print "New sock state: %s" %new_state    local_port = 8080    srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)#开启重用reuse    srv.bind( ('127.0.0.1', local_port) )    srv.listen(1)    print ("Listening on port: %s " %local_port)    while True:        try:            connection, addr = srv.accept()            print 'Connected by %s:%s' % (addr[0], addr[1])        except KeyboardInterrupt:            break        except socket.error, msg:            print '%s' % (msg,)'''simple SNTP serviceTIME1970 指1970年1月1日(也叫Epoch)通过UDP协议创建一个UDP套接字(SOCK_DGRAM),用于连接服务器。客户端要在一个数据包中把数据'\x1b' + 47 * '\0'发给SNTP服务器。UDP客户端分别使用sendto()和recvfrom()方法发送和接收数据。----客户端需要使用struct模块取出数据。我们所需的数据是数组中的第11个元素。我们要从取出的数据上减掉TIME1970,得到真正的当前时间'''import struct,timeTIME1970 = 2208988800LNTP_SERVER='0.uk.pool.ntp.org'def sntp_client():    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    data = '\x1b' + 47 * '\0'    client.sendto(data, (NTP_SERVER, 123))    data, address = client.recvfrom( 1024 )    if data:        print 'Response received from:', address    t = struct.unpack( '!12I', data )[10]    t -= TIME1970    print '\tTime=%s' % time.ctime(t)if __name__ == '__main__':    sntp_client()    #reuse_socket_addr()    '''    ./socket_timeout.py --host=192.168.1.70 --port=80 --file=/static/css/style.css    '''    # socker_err('192.168.1.70',80,'/1.txt')    # modify_buff()    # socker_err('192.168.1.70',80,'/1.txt')    #test_socket_modes()



0 0
原创粉丝点击