@@ -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