Socket Programming Using Python
Socket Programming Using Python
Socket Programming Using Python
Python
Dr. Amrita Chaturvedi
Position of UDP, TCP, IP in TCP/IP Suite
Introduction
• Application layer
– Communication for specific applications
– E.g., HyperText Transfer Protocol (HTTP), File Transfer
Protocol (FTP), Network News Transfer Protocol (NNTP)
• Transport layer
– Communication between processes (e.g., socket)
– Relies on network layer and serves the application layer
– E.g., TCP and UDP
• Network layer
– Logical communication between nodes
– Hides details of the link technology
– E.g., IP
Introduction: Transport Layer
• Provide logical communication
between application processes
running on different hosts application
transport
• Run on end hosts network
data link network
physical data link
23.12
TCP segment format
23.13
Challenges of Reliable Data Transfer
Solution
The value of rwnd = 5000 − 1000 = 4000. Host B can
receive only 4000 bytes of data before overflowing its
buffer. Host B advertises this value in its next segment to A.
Socket API
• Socket API
– Network programming interface
Application
Socket
Transport
API
TCP UDP
Network IP
BSD Socket API
• From a university, UC Berkeley (1980s)
• Endpoint of a connection
– Identified by IP address and Port number
l l e w … e poH! i H
• UDP treats them as separate messages
Hope you’re
Hi!
well
23
Python Sockets Modules
• Two basic sockets modules:
– Socket: provides the standard BSD Sockets API
– SocketServer: provides a server-centric class that
simplifies the development of network servers
• You can provide plug-in classes to do the
application-specific jobs of the server.
The Socket Module
• This module has everything you need to build socket servers and
clients.
• The socket method returns a socket object to which the socket
methods can be applied.
Class Methods for the Socket Module
Class Method Description
Socket Low-level networking interface (per the BSD
API)
socket.socket(family, type) Create and return a new socket object
socket.getfqdn(name) Convert a string quad dotted IP address to a
fully
qualified domain name
socket.gethostbyname(hostname) Resolve a hostname to a string quad dotted IP
address
socket.fromfd(fd, family, type) Create a socket object from an existing file
descriptor
The Socket Module
Instance Methods for the Socket Module
Instance Method Description
sock.bind ((adrs, port)) Bind the socket to the address and port
sock.accept() Return a client socket (with peer address
information)
sock.listen(backlog) Place the socket into the listening state, able to pend
backlog outstanding connection requests
sock.connect( (adrs, port) ) Connect the socket to the defined host and port
sock.recv( buflen[, flags] ) Receive data from the socket, up to buflen
bytes
sock.recvfrom( buflen[, flags] ) Receive data from the socket, up to buflen
bytes, returning also the remote host and port
from which the data came
sock.send( data[, flags] ) Send the data through the socket
sock.sendto( data[, flags], addr ) Send the data through the socket
sock.close() Close the socket
sock.getsockopt( lvl, optname ) Get the value for the specified socket option
sock.setsockopt( lvl, optname, val ) Set the value for the specified socket option
The SocketServer Module
import SocketServer
class hwRequestHandler( SocketServer.StreamRequestHandler ):
def handle( self ):
self.wfile.write("Hello World!\n")
server = SocketServer.TCPServer( ("", 2525), hwRequestHandler )
server.serve_forever()
Socket Programming in Python
• Socket is a conduit between the two applications
that can communicate with one another.
• Creating stream and Datagram Sockets:
– streamSock = socket.socket( socket.AF_INET,
socket.SOCK_STREAM )
– dgramSock = socket.socket( socket.AF_INET,
socket.SOCK_DGRAM )
– In each case a socket object is returned
• If your underlying operating system supports
IPv6, you can also specify socket.AF_INET6 to
create an IPv6 socket.
Socket Programming in Python
• To close a connected socket, you use the close
method:
– streamSock.close()
• Delete a socket with the del statement:
– del streamSock
• This statement permanently removes the
socket object. Attempting to reference the
socket thereafter produces an error.
Socket Programming in Python
• Socket addresses: An endpoint address for a
socket is a tuple consisting of an interface
address and a port number.
( '192.168.1.1', 80 )
• You can also use a fully qualified domain name
here, such as:
( 'www.ibm.com', 25 )
Server Sockets
• After you create the socket, you use the bind
method to bind an address to it, the listen
method to place it in the listening state, and
finally the accept method to accept a new client
connection.
sock = socket.socket( socket.AF_INET,
socket.SOCK_STREAM )
sock.bind( ('', 2525) )
sock.listen( 5 )
newsock, (remhost, remport) = sock.accept()
Server Sockets
• For this server, the address ('', 2525) is used
which means that the wildcard is used for the
interface address (''), allowing incoming
connections from any interface on the host.
You also bind to port number 2525.
• The accept method returns the new socket
object that represents the client connection
(newsock) and an address tuple (the remote
address and port number).
Server Sockets
• Creating a datagram server socket
sock = socket.socket( socket.AF_INET,
socket.SOCK_DGRAM )
sock.bind( ('', 2525) )
Client Sockets
• The mechanisms for creating and connecting
client sockets are similar to the setup of server
sockets.
• Upon creating a socket, an address is needed – to
identify where the socket should attach.
• Creating a stream socket and connecting to
server:
sock = socket.socket( socket.AF_INET,
socket.SOCK_STREAM )
sock.connect( ('192.168.1.1', 2525) )
Client Sockets
• Creating a datagram socket and connecting it
to the server
sock = socket.socket( socket.AF_INET,
sock.sock_DGRAM )
sock.connect( ('192.168.1.1', 2525) )
Stream Sockets I/O
• Simple python stream echo server: Server Code
import socket
srvsock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
srvsock.bind( ('', 23000) )
srvsock.listen( 5 )
while 1:
clisock, (remhost, remport) = srvsock.accept()
str = clisock.recv(100)
clisock.send( str )
clisock.close()
Stream Sockets I/O
• Simple python stream echo server: Client Code
import socket
clisock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
clisock.connect( ('', 23000) )
clisock.send("Hello World\n")
print clisock.recv(100)
clisock.close()
Datagram Sockets I/O
• Simple python datagram echo server: Server Code
import socket
dgramSock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
dgramSock.bind( ('', 23000) )
while 1:
msg, (addr, port) = dgramSock.recvfrom( 100 )
dgramSock.sendto( msg, (addr, port) )
Datagram Sockets I/O
• Simple python datagram echo client: Server Code
import socket
dgramSock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
dgramSock.sendto( "Hello World\n", ('', 23000) )
print dgramSock.recv( 100 )
dgramSock.close()
Socket Options
sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
# Get the size of the socket's send buffer
bufsize = sock.getsockopt( socket.SOL_SOCKET, socket.SO_SNDBUF )
# Get the state of the SO_REUSEADDR option
state = sock.getsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR )
# Enable the SO_REUSEADDR option
sock.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
Asynchronous I/O
• The select method allows you to multiplex events
for several sockets and for several different
events.
• For example, you can instruct select to notify you
when:
– a socket has data available,
– when it's possible to write data through a socket, and
– when an error occurs on a socket;
• You can perform these actions for many sockets
at the same time.
Asynchronous I/O
• Awaiting input from stdin
rlist, wlist, elist = select.select( [sys.stdin], [], [] )
print sys.stdin.read()
Asynchronous I/O
• Select method with multiple sockets
import socket
import select
sock1 = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
sock2 = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
sock1.connect( ('192.168.1.1', 25) )
sock2.connect( ('192.168.1.1', 25) )
while 1:
# Await a read event
rlist, wlist, elist = select.select( [sock1, sock2], [], [], 5 )
# Test for timeout
if [rlist, wlist, elist] == [ [], [], [] ]:
print "Five seconds elapsed.\n"
else:
# Loop through each socket in rlist, read and print the available data
for sock in rlist:
print sock.recv( 100 )
Building a Python Chat Server
The Chat Server Class
import socket
import select
class ChatServer:
def __init__( self, port ):
self.port = port;
self.srvsock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
self.srvsock.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
self.srvsock.bind( ("", port) )
self.srvsock.listen( 5 )
self.descriptors = [self.srvsock]
print 'ChatServer started on port %s' % port
def run( self ):
...
def broadcast_string( self, str, omit_sock ):
...
def accept_new_connection( self ):
The Chat Server run() Method
def run( self ):
while 1:
# Await an event on a readable socket descriptor
(sread, swrite, sexc) = select.select( self.descriptors, [], [] )
# Iterate through the tagged read descriptors
for sock in sread:
# Received a connect to the server (listening) socket
if sock == self.srvsock:
self.accept_new_connection()
else:
# Received something on a client socket
str = sock.recv(100)
The Chat Server run() Method
# Check to see if the peer socket closed
if str == '':
host,port = sock.getpeername()
str = 'Client left %s:%s\r\n' % (host, port)
self.broadcast_string( str, sock )
sock.close
self.descriptors.remove(sock)
else:
host,port = sock.getpeername()
newstr = '[%s:%s] %s' % (host, port, str)
self.broadcast_string( newstr, sock )
Helper Methods
• Accepting a new client connection on the chat server
def accept_new_connection( self ):
newsock, (remhost, remport) = self.srvsock.accept()
self.descriptors.append( newsock )
newsock.send("You're connected to the Python
chatserver\r\n")
str = 'Client joined %s:%s\r\n' % (remhost, remport)
self.broadcast_string( str, newsock )
Helper Methods
• Broadcasting a message to the chat group
def broadcast_string( self, str, omit_sock ):
for sock in self.descriptors:
if sock != self.srvsock and sock != omit_sock:
sock.send(str)
print str,
Instantiating a New Chat Server
myServer = ChatServer( 2626 )
myServer.run()
• Chaining methods
myServer = ChatServer( 2626 ).run()
#achieves the same result as above
Output from ChatServer
[plato]$ python pchatsrvr.py
ChatServer started on port 2626
Client joined 127.0.0.1:37993
Client joined 127.0.0.1:37994
[127.0.0.1:37994] Hello, is anyone there?
[127.0.0.1:37993] Yes, I'm here.
[127.0.0.1:37993] Client left 127.0.0.1:37993
Output from Chat Client #1
[plato]$ telnet localhost 2626
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
You're connected to the Python chatserver
Client joined 127.0.0.1:37994
[127.0.0.1:37994] Hello, is anyone there?
Yes, I'm here.
^]
telnet> close
Connection closed.
[plato]$
Output from Chat Client #2
[plato]$ telnet localhost 2626
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
You're connected to the Python chatserver
Hello, is anyone there?
[127.0.0.1:37993] Yes, I'm here.
[127.0.0.1:37993] Client left 127.0.0.1:37993