The Python interface is a straightforward transliteration of the Unix system call and library interface for sockets to Python’s object-oriented style: the socket() function returns a socket object whose methods implement the various socket system calls.
Sockets come in two varieties: server sockets and client sockets . After you create a server socket, you tell it to wait for connections. It will then listen at a certain network address (a combination of an IP address and a port number) until a client socket connects. The two can then communicate.
It is instantiated with up to three parameters: an address family (defaulting to socket.AF_INET), whether it’s a stream (socket.SOCK_STREAM, the default) or a datagram (socket.SOCK_DGRAM) socket, and a protocol.
Minimal server
import socket
s = socket.socket()
host = socket.gethostname()
port = 1234
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print('Got connection from', addr)
c.send(b'Thank you for connecting')
c.close()
Minimal client
import socket
s = socket.socket()
host = socket.gethostname()
port = 1234
s.connect((host, port))
print(s.recv(1024))
More informations about socket programming is on Socket Programming HOWTO.
Opening remote files
from urllib.request import urlopen
webpage = urlopen('http://www.python.org')
the variable webpage should now contain a file-like object linked to the Python web page.
Retreiving remote files
The urlopen function gives you a file-like object you can read from. If you would rather have urllib take care of downloading the file for you, storing a copy in a local file, you can use urlretrieve instead.
from urllib.request import urlretrieve
urlretrieve('http://www.python.org', 'python_webpage.html')
Other important modules
Module | Description |
---|---|
asynchat | Additional functionality for asyncore |
asyncore | Asynchronous socket handler |
cgi | Basic CGI support |
Cookie | Cookie object manipulation, mainly for servers |
cookielib | Client-side cookie support |
Support for e-mail messages (including MIME) | |
ftplib | FTP client module |
gopherlib | Gopher client module |
httplib | HTTP client module |
imaplib | IMAP4 client module |
mailbox | Reads several mailbox formats |
mailcap | Access to MIME configuration through mailcap files |
nntplib | NNTP client module |
poplib | POP client module |
robotparser | Support for parsing web server robot files |
SimpleXMLRPCServer | A simple XML-RPC server |
smtpd | SMTP server module |
smtplib | SMTP client module |
telnetlib | Telnet client module |
urlparse | Support for interpreting URLs |
xmlrpclib | Client support for XML-RPC |
#!/usr/bin/env python3
# Simple TCP client and server that send and receive 16 octets
import argparse, socket
def recvall(sock, length):
data = b''
while len(data) < length:
more = sock.recv(length - len(data))
if not more:
raise EOFError('was expecting %d bytes but only received'
' %d bytes before the socket closed'
% (length, len(data)))
data += more
return data
def server(interface, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((interface, port))
sock.listen(1)
print('Listening at', sock.getsockname())
while True:
print('Waiting to accept a new connection')
sc, sockname = sock.accept()
print('We have accepted a connection from', sockname)
print(' Socket name:', sc.getsockname())
print(' Socket peer:', sc.getpeername())
message = recvall(sc, 16)
print(' Incoming sixteen-octet message:', repr(message))
sc.sendall(b'Farewell, client')
sc.close()
print(' Reply sent, socket closed')
def client(host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
print('Client has been assigned socket name', sock.getsockname())
sock.sendall(b'Hi there, server')
reply = recvall(sock, 16)
print('The server said', repr(reply))
sock.close()
if __name__ == '__main__':
choices = {'client': client, 'server': server}
parser = argparse.ArgumentParser(description='Send and receive over TCP')
parser.add_argument('role', choices=choices, help='which role to play')
parser.add_argument('host', help='interface the server listens at;'
' host the client sends to')
parser.add_argument('-p', metavar='PORT', type=int, default=1060,
help='TCP port (default 1060)')
args = parser.parse_args()
function = choices[args.role]
function(args.host, args.p)
You can try instead of argparse other command line parse modules:
Remote Procedure Call (RPC) systems let you call a function in another process or on a remote server using the same syntax you would use when calling a routine in a local API or library. This is usefull in situations like:
XML-RPC is a convinient way to send messages across the Internet.
The nice thing about XML-RPC is that it transports native data structures- you can ship off lists, strings, dictionaries, and numbers.
Server
from xmlrpc.server import SimpleXMLRPCServer
def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x, y):
return x // y
# A simple server with simple arithmetic functions
server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_multicall_functions()
server.register_function(add, 'add')
server.register_function(subtract, 'subtract')
server.register_function(multiply, 'multiply')
server.register_function(divide, 'divide')
server.serve_forever()
Client
List available methods:
import xmlrpc.client
proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
multicall = xmlrpc.client.MultiCall(proxy)
multicall.add(7, 3)
multicall.subtract(7, 3)
multicall.multiply(7, 3)
multicall.divide(7, 3)
result = multicall()
print("7+3=%d, 7-3=%d, 7*3=%d, 7//3=%d" % tuple(result))
{ "data": { "sessionMaterial": { "id": "session-material:2018/tieto:network-programming:0", "title": "Network programming", "html": "\n \n \n\n <h2>Network Programming</h2>\n<h3>A socket module</h3>\n<p>The Python interface is a straightforward transliteration of the Unix system call and library interface for sockets to Python’s object-oriented style: the socket() function returns a socket object whose methods implement the various socket system calls.</p>\n<p>Sockets come in two varieties: server sockets and client sockets . After you create a server socket, you tell it to wait for connections. It will then listen at a certain network address (a combination of an IP address and a port number) until a client socket connects. The two can then communicate.</p>\n<p>It is instantiated with up to three parameters: an address family (defaulting to socket.AF_INET), whether it’s a stream (socket.SOCK_STREAM, the default) or a datagram (socket.SOCK_DGRAM) socket, and a protocol.</p>\n<p><strong>Minimal server</strong></p>\n<div class=\"highlight\"><pre><code>import socket\n\ns = socket.socket()\n\nhost = socket.gethostname()\nport = 1234\ns.bind((host, port))\n\ns.listen(5)\nwhile True:\n\n c, addr = s.accept()\n print('Got connection from', addr)\n c.send(b'Thank you for connecting')\n c.close()</code></pre></div><p><strong>Minimal client</strong></p>\n<div class=\"highlight\"><pre><code>import socket\n\ns = socket.socket()\n\nhost = socket.gethostname()\nport = 1234\n\ns.connect((host, port))\nprint(s.recv(1024))</code></pre></div><p>More informations about socket programming is on <a href=\"https://docs.python.org/3/howto/sockets.html\">Socket Programming HOWTO</a>.</p>\n<h3>The urllib and urllib2 modules</h3>\n<p><strong>Opening remote files</strong></p>\n<div class=\"highlight\"><pre><code>from urllib.request import urlopen\nwebpage = urlopen('http://www.python.org')</code></pre></div><p>the variable webpage should now contain a file-like object linked to the Python web page.</p>\n<p><strong>Retreiving remote files</strong></p>\n<p>The urlopen function gives you a file-like object you can read from. If you would rather have urllib take care of downloading the file for you, storing a copy in a local file, you can use urlretrieve instead.</p>\n<div class=\"highlight\"><pre><code>from urllib.request import urlretrieve\nurlretrieve('http://www.python.org', 'python_webpage.html')</code></pre></div><p><strong>Other important modules</strong></p>\n<table>\n<thead><tr>\n<th>Module</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>asynchat</td>\n<td>Additional functionality for asyncore</td>\n</tr>\n<tr>\n<td>asyncore</td>\n<td>Asynchronous socket handler</td>\n</tr>\n<tr>\n<td>cgi</td>\n<td>Basic CGI support</td>\n</tr>\n<tr>\n<td>Cookie</td>\n<td>Cookie object manipulation, mainly for servers</td>\n</tr>\n<tr>\n<td>cookielib</td>\n<td>Client-side cookie support</td>\n</tr>\n<tr>\n<td>email</td>\n<td>Support for e-mail messages (including MIME)</td>\n</tr>\n<tr>\n<td>ftplib</td>\n<td>FTP client module</td>\n</tr>\n<tr>\n<td>gopherlib</td>\n<td>Gopher client module</td>\n</tr>\n<tr>\n<td>httplib</td>\n<td>HTTP client module</td>\n</tr>\n<tr>\n<td>imaplib</td>\n<td>IMAP4 client module</td>\n</tr>\n<tr>\n<td>mailbox</td>\n<td>Reads several mailbox formats</td>\n</tr>\n<tr>\n<td>mailcap</td>\n<td>Access to MIME configuration through mailcap files</td>\n</tr>\n<tr>\n<td>nntplib</td>\n<td>NNTP client module</td>\n</tr>\n<tr>\n<td>poplib</td>\n<td>POP client module</td>\n</tr>\n<tr>\n<td>robotparser</td>\n<td>Support for parsing web server robot files</td>\n</tr>\n<tr>\n<td>SimpleXMLRPCServer</td>\n<td>A simple XML-RPC server</td>\n</tr>\n<tr>\n<td>smtpd</td>\n<td>SMTP server module</td>\n</tr>\n<tr>\n<td>smtplib</td>\n<td>SMTP client module</td>\n</tr>\n<tr>\n<td>telnetlib</td>\n<td>Telnet client module</td>\n</tr>\n<tr>\n<td>urlparse</td>\n<td>Support for interpreting URLs</td>\n</tr>\n<tr>\n<td>xmlrpclib</td>\n<td>Client support for XML-RPC</td>\n</tr>\n</tbody>\n</table>\n<h3>Simple TCP server and client</h3>\n<div class=\"highlight\"><pre><code>#!/usr/bin/env python3\n# Simple TCP client and server that send and receive 16 octets\n\nimport argparse, socket\n\ndef recvall(sock, length):\n data = b''\n while len(data) < length:\n more = sock.recv(length - len(data))\n if not more:\n raise EOFError('was expecting %d bytes but only received'\n ' %d bytes before the socket closed'\n % (length, len(data)))\n data += more\n return data\n\ndef server(interface, port):\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n sock.bind((interface, port))\n sock.listen(1)\n print('Listening at', sock.getsockname())\n while True:\n print('Waiting to accept a new connection')\n sc, sockname = sock.accept()\n print('We have accepted a connection from', sockname)\n print(' Socket name:', sc.getsockname())\n print(' Socket peer:', sc.getpeername())\n message = recvall(sc, 16)\n print(' Incoming sixteen-octet message:', repr(message))\n sc.sendall(b'Farewell, client')\n sc.close()\n print(' Reply sent, socket closed')\n\ndef client(host, port):\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n sock.connect((host, port))\n print('Client has been assigned socket name', sock.getsockname())\n sock.sendall(b'Hi there, server')\n reply = recvall(sock, 16)\n print('The server said', repr(reply))\n sock.close()\n\nif __name__ == '__main__':\n choices = {'client': client, 'server': server}\n parser = argparse.ArgumentParser(description='Send and receive over TCP')\n parser.add_argument('role', choices=choices, help='which role to play')\n parser.add_argument('host', help='interface the server listens at;'\n ' host the client sends to')\n parser.add_argument('-p', metavar='PORT', type=int, default=1060,\n help='TCP port (default 1060)')\n args = parser.parse_args()\n function = choices[args.role]\n function(args.host, args.p)</code></pre></div><p>You can try instead of argparse other command line parse modules:</p>\n<ul>\n<li>Docopt (pip install docopt)</li>\n<li>Click (pip install click)</li>\n<li>Invoke (pip install invoke)</li>\n</ul>\n<h3>RPC</h3>\n<p>Remote Procedure Call (RPC) systems let you call a function in another process or on a remote server using the same syntax you would use when calling a routine in a local API or library. This is usefull in situations like:</p>\n<ul>\n<li>Your program has a lot of work to do, and you want to spread it across several machines by making calls across the network, but without having to change the code that is making the call, which is now remote.</li>\n<li>You need data or information that is only available on another hard drive or network, and an RPC interface lets you easily send queries to another system to get back an answer.</li>\n</ul>\n<h3>XML-RPC</h3>\n<p>XML-RPC is a convinient way to send messages across the Internet.</p>\n<p>The nice thing about XML-RPC is that it transports native data structures- you can ship off lists, strings, dictionaries, and numbers.</p>\n<p><strong>Server</strong></p>\n<div class=\"highlight\"><pre><code>from xmlrpc.server import SimpleXMLRPCServer\n\ndef add(x, y):\n return x + y\n\ndef subtract(x, y):\n return x - y\n\ndef multiply(x, y):\n return x * y\n\ndef divide(x, y):\n return x // y\n\n# A simple server with simple arithmetic functions\nserver = SimpleXMLRPCServer(("localhost", 8000))\nprint("Listening on port 8000...")\nserver.register_multicall_functions()\nserver.register_function(add, 'add')\nserver.register_function(subtract, 'subtract')\nserver.register_function(multiply, 'multiply')\nserver.register_function(divide, 'divide')\nserver.serve_forever()</code></pre></div><p><strong>Client</strong></p>\n<p>List available methods:</p>\n<div class=\"highlight\"><pre><code>import xmlrpc.client\n\nproxy = xmlrpc.client.ServerProxy("http://localhost:8000/")\nmulticall = xmlrpc.client.MultiCall(proxy)\nmulticall.add(7, 3)\nmulticall.subtract(7, 3)\nmulticall.multiply(7, 3)\nmulticall.divide(7, 3)\nresult = multicall()\n\nprint("7+3=%d, 7-3=%d, 7*3=%d, 7//3=%d" % tuple(result))</code></pre></div>\n\n\n " } } }