Skip to content

Commit 00971a0

Browse files
committed
* further pushing for the in-class socket lib walkthrough
1 parent 2218e96 commit 00971a0

1 file changed

Lines changed: 224 additions & 0 deletions

File tree

source/presentations/week01.rst

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,227 @@ You can also find out about machines that are located elsewhere, for example::
344344
['www.rad.washington.edu'], # <- any aliases
345345
['128.95.247.84']) # <- all active IP addresses
346346

347+
Sockets in Python
348+
-----------------
349+
350+
To create a socket, you use the **socket** method of the ``socket`` library::
351+
352+
>>> foo = socket.socket()
353+
>>> foo
354+
<socket._socketobject object at 0x10046cec0>
355+
356+
Sockets in Python
357+
-----------------
358+
359+
A socket has some properties that are immediately important to us. These
360+
include the *family*, *type* and *protocol* of the socket::
361+
362+
>>> foo.family
363+
2
364+
>>> foo.type
365+
1
366+
>>> foo.proto
367+
0
368+
369+
Socket Families
370+
---------------
371+
372+
Think back a moment to our discussion of the *Internet* layer of the TCP/IP
373+
stack. There were a couple of different types of IP addresses:
374+
375+
.. class:: incremental
376+
377+
* IPv4 ('192.168.1.100')
378+
379+
* IPv6 ('2001:0db8:85a3:0042:0000:8a2e:0370:7334')
380+
381+
.. class:: incremental
382+
383+
The *family* of a socket corresponds to the type of address you use to make a
384+
connection to it.
385+
386+
A quick utility method
387+
----------------------
388+
389+
Let's explore these families for a moment. To do so, we're going to define
390+
a method we can use to read contstants from the ``socket`` library. It will
391+
take a single argument, the shared prefix for a defined set of constants::
392+
393+
>>> def get_constants(prefix):
394+
... """mapping of socket module constants to their names."""
395+
... return dict( (getattr(socket, n), n)
396+
... for n in dir(socket)
397+
... if n.startswith(prefix)
398+
... )
399+
...
400+
>>>
401+
402+
Socket Families
403+
---------------
404+
405+
Families defined in the ``socket`` library are prefixed by ``AF_``::
406+
407+
>>> families = get_constants('AF_')
408+
>>> families
409+
{0: 'AF_UNSPEC', 1: 'AF_UNIX', 2: 'AF_INET',
410+
11: 'AF_SNA', 12: 'AF_DECnet', 16: 'AF_APPLETALK',
411+
17: 'AF_ROUTE', 23: 'AF_IPX', 30: 'AF_INET6'}
412+
413+
.. class:: small incremental
414+
415+
*Your results may vary*
416+
417+
.. class:: incremental
418+
419+
Of all of these, the ones we care most about are ``2`` (IPv4) and ``30`` (IPv6).
420+
421+
Unix Domain Sockets
422+
-------------------
423+
424+
When you are on a machine with an operating system that is Unix-like, you will
425+
find another generally useful socket family: ``AF_UNIX``, or Unix Domain
426+
Sockets. Sockets in this family:
427+
428+
.. class:: incremental
429+
430+
* connect processes **on the same machine**
431+
432+
* are generally a bit slower than IPC connnections
433+
434+
* have the benefit of allowing the same API for programs that might run on one
435+
machine __or__ across the network
436+
437+
* use an 'address' that looks like a pathname ('/tmp/foo.sock')
438+
439+
Socket Families
440+
---------------
441+
442+
What is the *default* family for the socket we created just a moment ago?
443+
444+
.. class:: incremental
445+
446+
(remember we bound the socket to the symbol ``foo``)
447+
448+
Socket Types
449+
------------
450+
451+
The socket type determines how the socket handles connections. Socket type
452+
constants defined in the ``socket`` library are prefixed by ``SOCK_``::
453+
454+
>>> types = get_constants('SOCK_')
455+
>>> types
456+
{1: 'SOCK_STREAM', 2: 'SOCK_DGRAM',
457+
...}
458+
459+
.. class:: incremental
460+
461+
In general, the only two of these that are widely useful are ``1``
462+
(representing TCP type connections) and ``2`` (representing UDP type
463+
connections).
464+
465+
Socket Types
466+
------------
467+
468+
What is the *default* type for our generic socket, ``foo``?
469+
470+
Socket Protocols
471+
----------------
472+
473+
A socket also has a designated *protocol*. The constants for these are
474+
prefixed by ``IPPROTO``::
475+
476+
>>> protocols = get_constants('IPPROTO_')
477+
>>> protocols
478+
{0: 'IPPROTO_IP', 1: 'IPPROTO_ICMP',
479+
...,
480+
255: 'IPPROTO_RAW'}
481+
482+
.. class:: incremental
483+
484+
The choice of which protocol to use for a socket is determined by the type of
485+
activity the socket is intended to support. What messages are you needing to
486+
send?
487+
488+
Socket Protocols
489+
----------------
490+
491+
What is the *default* protocol used by our generic socket, ``foo``?
492+
493+
Address Information
494+
-------------------
495+
496+
When creating a socket, you can provide ``family``, ``type`` and ``protocol``
497+
as arguments to the constructor::
498+
499+
>>> bar = socket.socket(socket.AF_INET,
500+
... socket.SOCK_STREAM,
501+
... socket.IPPROTO_IP)
502+
...
503+
>>> bar
504+
<socket._socketobject object at 0x1005b8b40>
505+
506+
Address Information
507+
-------------------
508+
509+
But how do you find out the *right* values?
510+
511+
.. class:: incremental
512+
513+
You ask.
514+
515+
A quick utility method
516+
----------------------
517+
518+
Create the following function::
519+
520+
>>> def get_address_info(host, port):
521+
... for response in socket.getaddrinfo(host, port):
522+
... fam, typ, pro, nam, add = response
523+
... print 'family: ', families[fam]
524+
... print 'type: ', types[typ]
525+
... print 'protocol: ', protocols[pro]
526+
... print 'canonical name: ', nam
527+
... print 'socket address: ', add
528+
... print
529+
...
530+
>>>
531+
532+
On Your Own Machine
533+
-------------------
534+
535+
Now, ask your own machine what services are available on 'http'::
536+
537+
>>> get_address_info(socket.gethostname(), 'http')
538+
family: AF_INET
539+
type: SOCK_DGRAM
540+
protocol: IPPROTO_UDP
541+
canonical name:
542+
socket address: ('10.211.55.2', 80)
543+
544+
family: AF_INET
545+
...
546+
>>>
547+
548+
.. class:: incremental
549+
550+
What answers do you get?
551+
552+
On the Internet
553+
---------------
554+
555+
>>> get_address_info('www.google.com', 'http')
556+
>>> get_address_info('www.google.com', 'http')
557+
family: AF_INET
558+
type: SOCK_STREAM
559+
protocol: IPPROTO_TCP
560+
canonical name:
561+
socket address: ('74.125.129.105', 80)
562+
563+
family: AF_INET
564+
...
565+
>>>
566+
567+
.. class:: incremental
568+
569+
Try a few other servers you know about.
570+

0 commit comments

Comments
 (0)