760 likes | 781 Views
Python Networking. by Chris Seddon. Advanced Python. 1 . Networking 2. Sockets 3. SocketServer 4. Secure Sockets 5. Other Web Modules. 1. Networking. stream sockets datagram sockets web browsers web servers. 1. Hostnames and services. /etc/hosts host name Internet number
E N D
Python Networking byChris Seddon
Advanced Python • 1. Networking • 2. Sockets • 3. SocketServer • 4. Secure Sockets • 5. Other Web Modules
Networking • stream sockets • datagram sockets • web browsers • web servers 1
Hostnames and services • /etc/hosts • host name • Internet number • /etc/services • application • port number • /etc/inetd.conf • service • protocol • port number
/etc/hosts internet number official name aliases 127.1 local localhost loopback 192.19.140.200 blue 192.19.140.202 red 192.19.140.203 orange 192.19.140.207 indigo
/etc/services service port/protocol aliases echo 7/tcp echo 7/udp netstat 15/tcp ftp 21/tcp telnet 23/tcp hostnames 101/tcp hostname who 1034/udp whod
Sockets for IPC 192.56.40.2 192.56.40.7 sockets P1 port port P1 Internet domain /tmp/socket machine 2 Unix domain P2 machine 1
Socket Type • Application socket types • SOCK_DGRAM datagram • SOCK_STREAM virtual circuit • Diagnostic socket types • SOCK_RAW raw socket • SOCK_RDM reliably-delivered message • SOCK_SEQPACKET sequenced packets
Communications Domain • AF_BLUETOOTH Bluetooth protocol • AF_INET IPv4 protocols (TCP, UDP) • AF_INET6 IPv6 protocols (TCP, UDP) • AF_NETLINK Netlink Interprocess Communication • AF_PACKET Link-level packets • AF_TIPC Transparent Inter-Process Communication protocol • AF_UNIX UNIX domain protocols
Unix Domain • SOCK_STREAM • byte stream • bi-directional • like the telephone system • SOCK_DGRAM • message stream • bi-directional • like the mail system • Socket names are inodes • 108 character path name
Internet Domain • SOCK_STREAM TCP/IP • byte stream • bi-directional • built-in error checking • SOCK_DGRAM UDP/IP • message stream • bi-directional • no error checking • Socket names are 48 bit values • 32 bit Internet address • 16 bit port number
Internet Layered Model ftp ftpd TCP UDP TCP UDP IP IP ethernet protocol ethernet protocol Ethernet
Internet Packets 48 bit 32 bit 16 bit 34.f.6e.2.1d.a2 e.2d.63.a.12.b2 193.45.6.1 195.45.2.7 23 1945 data CRC Ethernet Address Internet Address Port Address
Internet Number Scheme N H H H Class A (0-127) N N H H Class B (128-191) N N N H Class C (192-223)
Socket Addresses • UNIX Domain AF_UNIX “/tmp/mysocket” import socket mySocket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) mySocket.bind("/tmp/mysocket") AF_INET 7001 197.46.74.6 Internet Domain import socket mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) mySocket.bind( (196.46.74.6, 7001) )
Stream Sockets Server Connection oriented socket() Client bind() socket() listen() connection establishment connect() accept() read() write() read() write() close() shutdown() close() shutdown()
Types of Stream Socket • Raw Sockets • created by socket() • must be converted to comms or listening socket • Comms Sockets • created by accept() / connect() • used to transfer data • cannot establish connections • Listening Sockets • converted by listen() • used to establish connections • cannot transfer data
“/tmp/socket” Socket Layout in the Kernel Server Client LISTEN SOCKET accept() connect() COMMS SOCKET listen() bind() COMMS SOCKET read() write()
Datagram Sockets Connectionless Server Client socket() socket() bind() bind() recvfrom() sendto() block until a request is received process request sendto() recvfrom()
Sockets 2
Stream Sockets - System Calls • socket create kernel data structure • bind attach to inode • listen convert to listening socket • accept create comms socket • connect request to connect to comms socket • read/write transfer data • send/recv transfer priority data • close/shutdown terminate connection • select monitor socket for activity • unlink remove named socket from kernel
Datagram Sockets - System Calls • socket create kernel data structure • bind attach to inode • connect remember last address • sendto/recfrom transfer data • send/recv transfer data (used with connect()) • close/shutdown terminate connection • unlink remove named socket from kernel
socket() • from socket import socket • sd = socket(domain, type) AF_UNIX AF_INET AF_XNS AF_SNA and more SOCK_STREAM SOCK_DGRAM
mySocket.bind("/tmp/mysocket") AF_UNIX mySocket.bind( (196.46.74.6, 7001) ) AF_INET bind() • sd.bind(address)
listen() and accept() • sd.listen(5) • commsSd, (remoteHost, remotePort) = sd.accept() max. no. of pending connection requests blocking call set by the call: address of socket requesting the connection new socket descriptor
connect() • sd.connect(address) sd.connect("/tmp/mysocket") AF_UNIX sd.connect( ("www.abc.com", 7001) ) AF_INET
Sending Data • Stream Sockets • must be connected • send - buffering may mean only part of a message sent • may need to repeat call until everything sent • sendall - calls send repeatedly until everything transmitted bytesSent = sd.send(message, flags) sd.sendall(message, flags) bytesSent = sd.sendto(message, flags, address) • Datagrams • must not be connected • recipient's address specified in call • buffering may mean only part of a message sent • may need to repeat call until everything sent
sendall() • sendall() is easier to use than send • None returned on success • exception thrown on failure • but unlike send() ... • can't determine how much data has been successfully transmitted while(len(message) > 0): bytesSent = sd.send(message) message = message[bytesSent:]
Receiving Data • Stream Sockets • must be connected • bufferSize specifies the maximum size of message • send - buffering may mean only part of a message sent • may need to repeat call until everything sent • sendall - calls send repeatedly until everything transmitted message = sd.recv(bufferSize, flags) (message, senderAddress) = sd.recfrom(bufferSize, flags) • Datagrams • must not be connected • recipient's address specified in call
Network Functions import socket ip_address = socket.gethostbyname(hostname) hostname = socket.gethostbyaddr(ip_address) fq_hostname = socket.getfqdn(ip_address) port_number = socket.getservbyname(service, protocol) dotted_address= socket.inet_ntoa(32bit_address) 32bit_address = socket.inet_pton(AF_INET,dottedAddress) host_address = ntohl(network_address) network_address = ntohs(host_address) hostname = socket.gethostname() (hostname, port) = socket.getsockname() (peer_hostname, peer_port) = socket.getpeername()
192 8 61 4 Address Conversion Functions inet_ntoa inet_pton "192.8.61.4"
Working with Lines of Text • Stream Sockets send data as a byte stream • with no regard to demarcation between lines of text • Network buffering ... • incomplete reads • received data might end half way along a line • Programmer's responsibility ... • to organize data into discrete lines • makefile() • overcomes these problems • builds a file like object • backing socket must be in blocking mode read only fileLikeObject = sd.makefile('r', 0) listOfLines = fileLikeObject.readlines()
Non Blocking Sockets ... • socket.setblocking(flags) • flags = 0 for non blocking • flags = 1 for blocking (default) • Non blocking sockets have timeouts ... • socket.settimeout(value) • value = 0.0 is the default clientDescriptor, clientAddress = sd.accept() clientDescriptor.setblocking(0) clientDescriptor.settimeout(15.0)
... Non Blocking Sockets • What if several blocking sockets are receiving data at the same time • how do you know which socket has data available • if you pick the wrong one you could block for a long time • C API • Unix ... • poll() and select() • Windows ... • select() • Python • select module • also look at asyncore and asynchat
Select • Uses 3 lists of socket descriptors • only active sockets get added to the lists sd1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sd2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sd3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) def pollSockets(): timeout = 5 readList, writeList, errorList = select.select( [sd1, sd2, sd3], [ ], [ ], timeout) if [ readList, writeList, errorList ] == [ [ ], [ ], [ ] ]: print timeout, "secs elapsed" else: for sd in readList: print id(sd), sd.recvfrom(100)
Poll • The poll() system call is only supported on Unix systems • Provides better scalability for network servers that service a large number of clients • the system call only requires listing the file descriptors of interest • select() builds a bitmap, turns on bits for the fds of interest, and then afterward the whole bitmap has to be linearly scanned again
SocketServer Module • SocketServer module • simplifies the task of writing network servers • Must create a Server object first from: • 1. TCPServer - server supporting the TCP • 2. UDPServer - server supporting the UDP • 3. UnixStreamServer - server implementing Unix domain stream-sockets (inherits from TCPServer) • 4. UnixDatagramServer - server implementing Unix domain datagrams (inherits from UDPServer) • Then create a Handler • provides a callback to process client requests
Servers • Use method from Socket • to send and receive • Forking and threading versions of each type of server can be created • using the ForkingMixIn and ThreadingMixIn mix-in classes BaseServer TCPServer UDPServer UnixStreamServer UnixDatagramServer
setup() handle() finish() BaseRequestHandler StreamRequestHandler DatagramRequestHandler self.rfile self.wfile Handlers • Must override handle() method • setup() and finish() are optional • Derived classes provide convenience attributes • rfile and wfile
Plug-in Handlers • Once you've written a handler • it can be plugged into any server • handlers are decoupled from servers class MyRequestHandlerA(SocketServer.StreamRequestHandler): .... class MyRequestHandlerB(SocketServer.DatagramRequestHandler): .... server = SocketServer.TCPServer( ("localhost", 7001), MyRequestHandlerA) server = SocketServer.UDPServer( ("localhost", 9001), MyRequestHandlerB)