Python includes several built-in modules as well as addon modules to implement different types of Internet communication. These modules simplify many of the tasks necessary to facilitate socket communication, email, file transfers, data streaming, HTTP requests, and more.
Because the communication possibilities with Python are so vast, this chapter focuses on phrases that implement simple socket servers, socket clients, and FTP clients, as well as POP3 and SMTP mail clients that can be easily incorporated into Python scripts.
Example .
sSock = socket(AF_INET, SOCK_STREAM) sSock.bind((serverHost, serverPort)) sSock.listen(3) conn, addr = sSock.accept() data = conn.recv(1024)
The socket module included with Python provides a generic interface to a variety of low-level socket programming. This phrase discusses how to implement a low-level socket server using the socket module.
The first step in implementing a server-side socket interface is to create the server socket by calling -socket(family, type [, proto])
, which creates and returns a new socket. family
refers to the address family listed in Table 7.1, type
refers to the socket types listed in Table 7.2, and proto
refers to the protocol number, which is typically omitted except when working with raw sockets.
Table 7.2. Socket Types for Python Sockets
Type | Description |
---|---|
SOCK_STREAM | Opens an existing file for reading. |
SOCK_DGRAM | Opens a file for writing. If the file already exists, the contents are deleted. If the file does not already exist, a new one is created. |
SOCK_RAW | Opens an existing file for updating, keeping the existing contents intact. |
SOCK_RDM | Opens a file for both reading and writing. The existing contents are kept intact. |
SOCK_SEQPACKET | Opens a file for both writing and reading. The existing contents are deleted. |
Once the socket has been created, it must be bound to an address and port using the bind(
address
)
method, where address
refers to a tuple in the form of (hostname, port). If the hostname is an empty string, the server will allow connections on any available Internet interface on the system.
After the socket has been bound to an interface, it can be activated by invoking the listen(
backlog
)
method, where backlog
is an integer that indicates how many pending connections the system should queue before rejecting new ones.
Once the socket is active, implement a while
loop to wait for client connections using the accept()
method. Once a client connection has been accepted, data can be read from the connection using the recv
(buffsize [,flags])
method. The send
(string [,flags])
method is used to write a response back to the client.
from socket import * serverHost = '' # listen on all interfaces serverPort = 50007 #Open socket to listen on sSock = socket(AF_INET, SOCK_STREAM) sSock.bind((serverHost, serverPort)) sSock.listen(3) #Handle connections while 1: #Accept a connection conn, addr = sSock.accept() print 'Client Connection: ', addr while 1: #Receive data data = conn.recv(1024) if not data: break print 'Server Received: ', data newData = data.replace('Client', 'Processed') #Send response conn.send(newData) #Close Connection conn.close()
Client Connection: ('137.65.77.24', 1678) Server Received: Client Message1 Server Received: Client Message2
Output from server_socket.py code
Example .
sSock = socket(AF_INET, SOCK_STREAM) sSock.connect((serverHost, serverPort)) sSock.send(item) data = sSock.recv(1024)
The socket module is also used to create a client-side socket that talks to the server-side socket discussed in the previous phrase.
The first step in implementing a client-side socket interface is to create the client socket by calling socket
(family, type [, proto])
, which creates and returns a new socket. family
refers to the address family listed previously in Table 7.1, type
refers to the socket types listed previously in Table 7.2, and proto
refers to the protocol number, which is typically omitted except when working with raw sockets.
Once the client-side socket has been created, it can connect to the server socket using the connect(
address
)
method, where address
refers to a tuple in the form of (hostname, port).
To connect to a server-socket on the local computer, use localhost
as the hostname in the server address tuple.
After the client-side socket has connected to the server-side socket, data can be sent to the server using the send
(string [,flags])
method. The response from the server is received from the connection using the recv
(buffsize [,flags])
method.
import sys from socket import * serverHost = 'localhost' serverPort = 50008 message = ['Client Message1', 'Client Message2'] if len(sys.argv) > 1: serverHost = sys.argv[1] #Create a socket sSock = socket(AF_INET, SOCK_STREAM) #Connect to server sSock.connect((serverHost, serverPort)) #Send messages for item in message: sSock.send(item) data = sSock.recv(1024) print 'Client received: ', 'data' sSock.close()
Client received: 'Processed Message1' Client received: 'Processed Message2'
Output from client_socket.py code
Example .
serv= SocketServer.TCPServer(("",50008),myTCPServer) serv.serve_forever() . . . line = self.rfile.readline() self.wfile.write("%s: %d bytes successfully received." % (sck, len(line)))
In addition to the socket module, Python includes the SocketServer module to provide you with TCP, UDP, and UNIX classes that implement servers. These classes have methods that provide you with a much higher level of socket control.
To implement a SocketServer to handle streaming requests, first define the class to inherit from the SocketServer.StreamRequestHandler
class.
To handle the streaming requests, override the handle method to read and process the streaming data. The rfile.readline()
function reads the streaming data until a newline character is encountered, and then returns the data as a string.
To send data back to the client from the streaming server, use the wfile.write(
string
)
command to write the string back to the client.
Once you have defined the server class and overridden the handle
method, create the server object by invoking SocketServer.TCPServer(
address, handler
)
, where address
refers to a tuple in the form of (hostname, port
) and handler
refers to your defined server class.
After the server object has been created, you can start handling connections by invoking the server object’s handle_request()
or serve_forever()
method.
In addition to the TCPServer
method, you can also use the UDPServer
, UnixStreamServer
, and UnixDatagramServer
methods to create other types of servers.
import socket import string class myTCPServer(SocketServer.StreamRequestHandler): def handle (self): while 1: peer = self.connection.getpeername()[0] line = self.rfile.readline() print "%s wrote: %s" % (peer, line) sck = self.connection.getsockname()[0] self.wfile.write("%s: %d bytes successfuly received." % (sck, len(line))) #Create SocketServer object serv = SocketServer.TCPServer(("",50008),myTCPServer) #Activate the server to handle clients serv.serve_forever()
stream_server.py
137.65.76.8 wrote: Hello 137.65.76.8 wrote: Here is today's weather. 137.65.76.8 wrote: Sunny 137.65.76.8 wrote: High: 75 137.65.76.8 wrote: Low: 58 137.65.76.8 wrote: bye
Output from stream_server.py code
Example .
sSock = socket(AF_INET, SOCK_STREAM) sSock.connect((serverHost, serverPort)) line = raw_input("Send to %s: " % (serverHost)) sSock.send(line+' ') data = sSock.recv(1024)
To send streaming data to the streaming server described in the previous task, first create the client socket by calling socket
(family, type
[
, proto
])
, which creates and returns a new socket.
Once the streaming client-side socket has been created, it can connect to the streaming server using the connect(
address
)
method, where address
refers to a tuple in the form of (hostname, port).
After the streaming client-side socket has connected to the server-side socket, data can be streamed to the server by formatting a stream of data that ends with the newline character and sending it to the server using the send
(string
[
,flags
])
method.
A response from the server is received from the socket using the recv
(buffsize
[
,flags
])
method.
import sys from socket import * serverHost = 'localhost' serverPort = 50008 if len(sys.argv) > 1: serverHost = sys.argv[1] #Create socket sSock = socket(AF_INET, SOCK_STREAM) #Connect to server sSock.connect((serverHost, serverPort)) #Stream data to server. line = "" while line != 'bye': line = raw_input("Send to %s: " % (serverHost)) sSock.send(line+' ') data = sSock.recv(1024) print 'data' sSock.shutdown(0) sSock.close()
stream_client.py
Send to 137.65.76.28: Hello '137.65.77.28: 6 bytes received.' Send to 137.65.76.28: Here is today's weather. '137.65.77.28: 25 bytes received.' Send to 137.65.76.28: Sunny '137.65.77.28: 6 bytes received.' Send to 137.65.76.28: High: 75 '137.65.77.28: 9 bytes received.' Send to 137.65.76.28: Low: 58 '137.65.77.28: 8 bytes received.' Send to 137.65.76.28: bye '137.65.77.28: 4 bytes received.'
Output from stream_client.py code
Example .
mMessage = ('From: %s To: %s Date: %s Subject: %s %s ' % (From, To, Date, Subject, Text)) s = smtplib.SMTP('mail.sfcn.org') rCode = s.sendmail(From, To, mMessage) s.quit()
The smtplib module included with Python provides simple access to SMTP servers that allow you to connect and quickly send mail messages from your Python scripts.
Mail messages must be formatted properly for the To, From, Date, Subject, and text fields to be processed properly by the SMTP mail server. The code in send_smtp.py shows the proper formatting for the mail message, including the item headers and newline characters.
Once the mail message is properly formatted, connect to the SMTP server using the smtplib.SMTP(host [,port])
method. If it is necessary to log in to the SMTP server, use the login(user, password)
method to complete an authentication.
Once connected to the SMTP server, the formatted message can be sent using sendmail(
from, to, message
)
, where from
is the sending email address string, to
specifies a list of destination email address strings, and message
is the formatted message string.
After you are finished sending messages, use the quit()
method to close the connection to the SMTP server.
import smtplib import time From = "[email protected]" To = ["[email protected]"] Date = time.ctime(time.time()) Subject = "New message from Brad Dayley." Text = "Message Text" #Format mail message mMessage = ('From: %s To: %s Date: %s Subject: %s %s ' % (From, To, Date, Subject, Text)) print 'Connecting to Server' s = smtplib.SMTP('mail.sfcn.org') #Send mail rCode = s.sendmail(From, To, mMessage) s.quit() if rCode: print 'Error Sending Message' else: print 'Message Sent Successfully'
send_smtp.py
Connecting to Server Message Sent Successfully
Output from send_smtp.py code
Also, see Figure 7.1.
Example .
mServer = poplib.POP3('mail.sfcn.org') mServer.user(getpass.getuser()) mServer.pass_(getpass.getpass()) numMessages = len(mServer.list()[1]) for msg in mServer.retr(mList+1)[1]:
The poplib module included with Python provides simple access to POP3 mail servers that allow you to connect and quickly retrieve messages using your Python scripts.
Connect to the POP3 mail server using the poplib.POP3(
host
[,port [,keyfile [,certfile]]])
method, where host
is the address of the POP3 mail server. The optional port argument defaults to 995. The other optional arguments, keyfile
and certfile
, refer to the PEM-formatted private key and certificate authentication files, respectively.
To log in to the POP3 server, the code in pop3_mail.py calls the user(username)
and pass_(password)
methods of the POP3 server object to complete the authentication.
The example uses getuser()
and getpass()
from the getpass module to retrieve the username and password. The username and password can also be passed in as clear text strings.
After it’s authenticated to the POP3 server, the poplib module provides several methods to manage the mail messages. The example uses the list()
method to retrieve a list of messages in the tuple format (
response, msglist, size
)
, where response
is the server’s response code, msglist
is a list of messages in string format, and size
is the size of the response in bytes.
To retrieve only a single message, use retr(msgid)
. The retr
method returns the message numbered msgid in the form of a tuple (response, lines, size), where response is the server response, lines is a list of strings that compose the mail message, and size is the total size in bytes of the message.
The lines list
returned by the retr
method includes all lines of the messages, including the header. To retrieve specific information, such as the recipient list, the lines list
must be parsed.
When you are finished managing the mail messages, use the quit()
method to close the connection to the POP3 server.
import poplib import getpass mServer = poplib.POP3('mail.sfcn.org') #Login to mail server mServer.user(getpass.getuser()) mServer.pass_(getpass.getpass()) #Get the number of mail messages numMessages = len(mServer.list()[1]) print "You have %d messages." % (numMessages) print "Message List:" #List the subject line of each message for mList in range(numMessages) : for msg in mServer.retr(mList+1)[1]: if msg.startswith('Subject'): print ' ' + msg break mServer.quit()
password: You have 10 messages. Message List: Subject: Static IP Info Subject: IP Address Change Subject: Verizon Wireless Online Statement Subject: New Static IP Address Subject: Your server account has been created Subject: Looking For New Home Projects? Subject: PDF Online - cl_scr_sheet.xls Subject: Professional 11 Upgrade Offer Subject: #1 Ball Played at the U.S. Open Subject: Chapter 3 submission
Output from pop3_mail.py code
Example .
ftp = ftplib.FTP('ftp.novell.com', 'anonymous', '[email protected]') gFile = open("readme.txt", "wb") ftp.retrbinary('RETR Readme', gFile.write) gFile.close() ftp.quit()
A common and extremely useful function of Python scripts is to retrieve files to be processed using the FTP protocol. The ftplib module included in Python allows you to use Python scripts to quickly attach to an FTP server, locate files, and then download them to be processed locally.
To open a connection to the FTP server, create an FTP server object using the ftplib.FTP([host [, user [, passwd]]])
method.
Once the connection to the server is opened, the methods in the ftplib module provide most of the FTP functionality to navigate the directory structure, manage files and directories, and, of course, download files.
The example shows connecting to an FTP server, listing the files and directories in the FTP server root directory using the dir()
method, and then changing the directory using the cwd(path)
method. In the example, the contents of the file Readme are downloaded from the FTP server and written to the local file readme.txt using the retrbinary(command, callback [, blocksize [, reset]])
method.
After you are finished downloading/managing the files on the FTP server, use the quit()
method to close the connection.
import ftplib #Open ftp connection ftp = ftplib.FTP('ftp.novell.com', 'anonymous', '[email protected]') #List the files in the current directory print "File List:" files = ftp.dir() print files #Get the readme file ftp.cwd("/pub") gFile = open("readme.txt", "wb") ftp.retrbinary('RETR Readme', gFile.write) gFile.close() ftp.quit() #Print the readme file contents print " Readme File Output:" gFile = open("readme.txt", "r") buff = gFile.read() print buff gFile.close()
ftp_client.py
File List: -rw-r-r- 1 root root 720 Dec 15 2005 README.html -rw-r-r- 1 root root 1406 Dec 15 2005 Readme drwxrwxrwx 2 root root 53248 Jun 26 18:10 incoming drwxrwxrwx 2 root root 16384 Jun 26 17:53 outgoing drwxr-xr-x 3 root root 4096 May 12 16:12 partners drwxr-xr-x 2 root root 4096 Apr 4 18:24 priv drwxr-xr-x 4 root root 4096 May 25 22:20 pub None Readme File Output: ************************************************ Before you download any software product you must read and agree to the following: . . .
Output from ftp_client.py code