高级网络操作

Python对TCP/IP网络的支持,为不同类型的程序提供了很多有用的特性

1>半开放socket(Half-open sockets),它可以使你关闭一个方向上的通信

2>超时(Timeouts),它在等待了一定时间后,如果没有可以连接的网路则产生异常

3>传送字符串和标记字符串结束的技巧

4>网络字节命令,一般用于C-based协议的通信

5>广播(Broadcasts),它会同时向多个机器发送数据

6>使用IPV6,下一代互联网协议

7>绑定到特殊的地址或接口

8>使用poll和select同时查找多个不同的事件

 

超时:

eg:

 

#Echo Server with Timeouts --------- timeoutserver.py



import socket,traceback



host = ''

port = 51423



s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

s.bind((host,port))

s.listen(1)





while True:

    try:

        clientsock,clientaddr = s.accept()

    except KeyboardInterrupt:

        raise

    except:

        traceback.print_exec()

        continue

    clientsock.settimeout(5)



    try:

        print "Got connection from",clientsock.getpeername()

        while True:

            data = clientsock.recv(4096)

            if not len(data): 

                break

            clientsock.sendall(data)

    except (KeyboardInterrupt,SystemExit):

        raise

    except socket.timeout:

        pass

    except:

        traceback.print_exc()



    try:

        clientsock.close()

    except KeyboardInterrupt:

        raise

    except:

        traceback.print_exc()

 

网络字节:

eg:

#Network Byte Order ----  nbo.py



import struct,sys



def htons(num):

    return struct.pack('!H',num)



def htonl(num):

    return struct.pack('!I',num);



def ntohs(data):

    return struct.unpack('!H',data)[0]



def ntohl(data):

    return struct.unpack('!I',data)[0]



def sendstring(data):

    return htonl(len(data))+data



print "Enter a string:"

str = sys.stdin.readline().rstrip()

print repr(sendstring(str))

 

广播:

服务器:

#UDP Broadcase Server  ---   bcastreceiver.py



import socket,traceback



host = ''

port = 51423



s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)

s.bind((host,port))



while True:

    try:

        message,address =s.recvfrom(8192)

        print "Got data from ",address

        s.sendto("I am here",address)

    except (KeyboardInterrupt,SystemExit):

        raise

    except:

        traceback.print_exc()

 

客户端:

#Broadcast Sender ---- bcastsender.py



import socket,sys

dest = ('<broadcast>',51423)



s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)

s.sendto("Hello",dest)



print "Looking for replies; press Ctrl-C to stop."



while True:

    (buf,address) = s.recvfrom(2048)

    if not len(buf):

        break

    print "Received from %s: %s" % (address,buf)

 

 

IPV6:

#getaddrinfo() display

#Give a host and a port on the command line



import socket,sys



host,port = sys.argv[1:]



results = socket.getaddrinfo(host,port,0,socket.SOCK_STREAM)



for result in results:

    print "-"*60



    if result[0] == socket.AF_INET:

        print "Family: AF_INET"

    elif result[0] == socket.AF_INET6:

        print "Family: AF_INET6"

    else:

        print "Family:",result[0]



    if result[1] == socket.SOCK_STREAM:

        print "Socket Type: SOCK_STREAM"

    elif result[1] == socket.SOCK_DGRAM:

        print "Socket Type: SOCK_DGRAM"



    print "Protocol:",result[2]

    print "Canonical Name:",result[3]

    print "Socket Address:",result[4]

 

Family参数:

#Connect Example with ipv6 Awareness  -------------   ipv6connect.py



import socket,sys



def getaddrinfo_pref(host,port,socktype,familypreference=socket.AF_INET):

    """Given a host,port,and socktype (usually socket.SOCK_STREAM or socket.SOCK_DGRAM)),

    looks up information with both IPV4 and IPV6.

    If information is found corresponding to familypreference,it is returned.

    Otherwise,any information found is returned.The family preference defaults

    to IPV4(socket.AF_INET) but you could alse set it to socket.AF_INET6 for IPV6



    The return value is the appropriate tuple returned from

    socket.getaddrinfo()."""



    results = socket.getaddrinfo(host,port,0,socktype)



    for result in results:

        if result[0] == familypreference:

            return result

    return results[0]



host = sys.argv[1]

port = 'http'



c = getaddrinfo_pref(host,port,socket.SOCK_STREAM)

print "Connecting to",c[4]



s = socket.socket(c[0],c[1])

s.connect(c[4])

s.sendall("HEAD / HTTP/1.0\n\n")



while True:

    buf = s.recv(4096)



    if not len(buf):

        break

    sys.stdout.write(buf)

 

绑定地址:

#Echo Server Bound to Specific Address

#bindserver.py



import socket,traceback



host = '127.0.0.1'

port = 51423





s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

s.bind((host,port))

s.listen(1)





while True:

    clientsock,clientaddr = s.accept()



    print "Got connection from",clientsock.getpeername()



    while True:

        data = clientsock.recv(4096)

        if not len(data):

            break

        clientsock.sendall(data)



    clientsock.close()

 

 

poll:

#Nonblocking I/O

#pollclient.py



import socket,sys,select





port = 51423

host = 'localhost'



spinsize = 10

spinpos = 0

spindir = 1



def spin():

    global spinsize,spinpos,spindir



    spinstr = '.' * spinpos + '|' + '.'*(spinsize-spinpos-1)

    sys.stdout.write('\r'+spinstr+' ')

    sys.stdout.flush()



    spinpos += spindir



    if spinpos < 0:

        spindir = 1

        spinpos = 1

    elif spinpos >= spinsize:

        spinpos -= 2

        spindir = -1



s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((host,port))



p = select.poll()



p.register(s.fileno(),select.POLLIN | select.POLLERR | select.POLLHUP)



while True:

    results = p.poll(50)



    if len(results):

        if results[0][1] == select.POLLIN:

            data = s.recv(4096)

            if not len(data):

                print ("\rRemove end closed connection ; exiting.")

                break

            sys.stdout.write("\rReceived: " + data)

            sys.stdout.flush()



        else:

            print "\rProblem occurred exitng."

            sys.exit(0)

    spin()

 

select:

#selectclient.py



import socket,sys,select



port = 51423

host = 'localhost'



spinsize = 10

spinpos = 0

spindir = 1



def spin():

    global spinsize,spinpos,spindir



    spinstr = '.' * spinpos + '|' + '.' *(spinsize - spinpos -1)

    sys.stdout.write('\r' + spinstr +' ')

    sys.stdout.flush()



    spinpos += spindir



    if spinpos < 0:

        spindir = 1

        spinpos = 1

    elif spinpos >= spinsize:

        spinpos -= 2

        spindir = -1



s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((host,port))



while True:

    infds,outfds,errfds = select.select([s],[],[s],0.05)



    if len(infds):

    #Normally,one would use something like "for fd in infds" here

    #We don't bother since there will only ever be a single file

    #descriptor there.



        data = s.recv(4096)

        if not len(data):

            print("\rRemote end closed connection; Exiting.")

            break

        sys.stdout.write("\rReceived: " + data)

        sys.stdout.flush()



    if len(errfds):

        print "\rProblen occurred; exiting."

        sys.exit(0)

    spin()

 

 

 

你可能感兴趣的:(网络)