forked from cewing/training.python_web
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathweek01.html
More file actions
688 lines (683 loc) · 27 KB
/
Copy pathweek01.html
File metadata and controls
688 lines (683 loc) · 27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.9.1: http://docutils.sourceforge.net/" />
<meta name="version" content="S5 1.1" />
<title>Internet Programming with Python</title>
<link rel="stylesheet" href="ui/uw_pce_theme/pretty.css" type="text/css" />
<!-- configuration parameters -->
<meta name="defaultView" content="slideshow" />
<meta name="controlVis" content="hidden" />
<!-- style sheet links -->
<script src="ui/uw_pce_theme/slides.js" type="text/javascript"></script>
<link rel="stylesheet" href="ui/uw_pce_theme/slides.css"
type="text/css" media="projection" id="slideProj" />
<link rel="stylesheet" href="ui/uw_pce_theme/outline.css"
type="text/css" media="screen" id="outlineStyle" />
<link rel="stylesheet" href="ui/uw_pce_theme/print.css"
type="text/css" media="print" id="slidePrint" />
<link rel="stylesheet" href="ui/uw_pce_theme/opera.css"
type="text/css" media="projection" id="operaFix" />
</head>
<body>
<div class="layout">
<div id="controls"></div>
<div id="currentSlide"></div>
<div id="header">
</div>
<div id="footer">
<h1>Internet Programming with Python</h1>
<h2><a class="reference external" href="http://github.com/cewing/training.python_web">View document source</a>.
</h2>
</div>
</div>
<div class="presentation">
<div class="slide" id="slide0">
<h1 class="title">Internet Programming with Python</h1>
<img alt="img/python.png" class="align-left" src="img/python.png" style="width: 33%;" />
<p>Week 1: Networking and Sockets</p>
<p class="intro-blurb">Wherein we learn about the basic structure of the internet and explore the
building blocks that make it possible.</p>
</div>
<div class="slide" id="but-first">
<h1>But First</h1>
<p class="big-centered">Mumbo-Jumbo</p>
</div>
<div class="slide" id="id1">
<h1>But First</h1>
<p>Class presentations are available online for your use</p>
<p><a class="reference external" href="http://github.com/cewing/training.python_web">http://github.com/cewing/training.python_web</a></p>
<p>Licensed with Creative Commons BY-NC-SA</p>
<ul class="simple">
<li>You must attribute the work</li>
<li>You may not use the work for commercial purposes</li>
<li>You have to share your versions just like this one</li>
</ul>
<p>Find mistakes? See improvements? Make a pull request.</p>
</div>
<div class="slide" id="id2">
<h1>But First</h1>
<p>Class Structure</p>
<ul class="simple">
<li>~20 minutes of Review and Discussion</li>
<li>5 minute break</li>
<li>~1 hour of Lecture and Exercises</li>
<li>10 minute break</li>
<li>~1 hour of Lab Time</li>
<li>5 minute break</li>
<li>~20 minutes of Lightning Talks</li>
</ul>
</div>
<div class="slide" id="id3">
<h1>But First</h1>
<p>I'll spend a lot of time talking</p>
<p class="incremental">Don't make the mistake of thinking this means I know everything</p>
<p class="incremental">Each of us has domain expertise, share it</p>
</div>
<div class="slide" id="id4">
<h1>But First</h1>
<p class="big-centered">Introductions</p>
</div>
<div class="slide" id="finally">
<h1>Finally</h1>
<p class="big-centered">And now, let us begin!</p>
</div>
<div class="slide" id="questions-from-the-reading">
<h1>Questions From the Reading?</h1>
<p class="big-centered">do you have any?</p>
</div>
<div class="slide" id="computer-communications">
<h1>Computer Communications</h1>
<img alt="img/network_topology.png" class="align-left" src="img/network_topology.png" style="width: 40%;" />
<ul class="incremental simple">
<li>processes can communicate</li>
<li>inside one machine</li>
<li>between two machines</li>
<li>among many machines</li>
</ul>
<p class="image-credit">image: <a class="reference external" href="http://en.wikipedia.org/wiki/Internet_Protocol_Suite">http://en.wikipedia.org/wiki/Internet_Protocol_Suite</a></p>
</div>
<div class="slide" id="id5">
<h1>Computer Communications</h1>
<img alt="img/data_in_tcpip_stack.png" class="align-left" src="img/data_in_tcpip_stack.png" style="width: 55%;" />
<ul class="incremental simple">
<li>Process divided into 'layers'</li>
<li>'Layers' are mostly arbitrary</li>
<li>Different descriptions have different layers</li>
<li>Most common is the 'TCP/IP Stack'</li>
</ul>
<p class="image-credit">image: <a class="reference external" href="http://en.wikipedia.org/wiki/Internet_Protocol_Suite">http://en.wikipedia.org/wiki/Internet_Protocol_Suite</a></p>
</div>
<div class="slide" id="the-tcp-ip-stack-link">
<h1>The TCP/IP Stack - Link</h1>
<p>The bottom layer is the 'Link Layer'</p>
<ul class="incremental simple">
<li>Deals with the physical connections between machines, 'the wire'</li>
<li>Packages data for physical transport</li>
<li>Executes transmission over a physical medium<ul>
<li>what that medium is is arbitrary</li>
</ul>
</li>
<li>Primarily uses the Network Interface Card (NIC) in your computer</li>
</ul>
</div>
<div class="slide" id="the-tcp-ip-stack-internet">
<h1>The TCP/IP Stack - Internet</h1>
<p>Moving up, we have the 'Internet Layer'</p>
<ul class="incremental simple">
<li>Deals with addressing and routing<ul>
<li>Where are we going?</li>
<li>What path do we take to get there?</li>
</ul>
</li>
<li>Agnostic as to physical medium (IP over Avian Carrier - IPoAC)</li>
<li>Makes no promises of reliability</li>
<li>Two addressing systems<ul class="incremental">
<li>IPv4 (current, limited '192.168.1.100')</li>
<li>IPv6 (future, 3.4 x 10^38 addresses, '2001:0db8:85a3:0042:0000:8a2e:0370:7334')</li>
</ul>
</li>
</ul>
</div>
<div class="slide" id="id6">
<h1>The TCP/IP Stack - Internet</h1>
<p class="big-centered">That's 4.3 x 10^28 addresses <em>per person alive today</em></p>
</div>
<div class="slide" id="the-tcp-ip-stack-transport">
<h1>The TCP/IP Stack - Transport</h1>
<p>Next up is the 'Transport Layer'</p>
<ul class="incremental simple">
<li>Deals with transmission and reception of data<ul>
<li>error correction, flow control, congestion management</li>
</ul>
</li>
<li>Common protocols include TCP & UDP<ul>
<li>TCP: Tranmission Control Protocol</li>
<li>UDP: User Datagram Protocol</li>
</ul>
</li>
<li>Not all Transport Protocols are 'reliable'<ul class="incremental">
<li>TCP ensures that dropped packets are resent</li>
<li>UDP makes no such assurance</li>
<li>Reliability is slow and expensive</li>
</ul>
</li>
</ul>
</div>
<div class="slide" id="id7">
<h1>The TCP/IP Stack - Transport</h1>
<p>The 'Transport Layer' also establishes the concept of a <strong>port</strong></p>
<ul class="incremental simple">
<li>IP Addresses designate a specific <em>machine</em> on the network</li>
<li>A <strong>port</strong> provides addressing for individual <em>applications</em> in a single host</li>
<li>192.168.1.100:80 (the <em>:80</em> part is the <strong>port</strong>)</li>
</ul>
<p class="incremental">This means that you don't have to worry about information intended for your
web browser being accidentally read by your email client.</p>
</div>
<div class="slide" id="id8">
<h1>The TCP/IP Stack - Transport</h1>
<p>There are certain <strong>ports</strong> which are commonly understood to belong to given
applications or protocols:</p>
<ul class="incremental simple">
<li>80/443 - HTTP/HTTPS</li>
<li>20 - FTP</li>
<li>22 - SSH</li>
<li>23 - Telnet</li>
<li>25 - SMTP</li>
<li>...</li>
</ul>
<p class="small">(see <a class="reference external" href="http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers">http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers</a>)</p>
</div>
<div class="slide" id="id9">
<h1>The TCP/IP Stack - Transport</h1>
<p>Ports are grouped into a few different classes</p>
<ul class="incremental simple">
<li>Ports numbered 0 - 1023 are <em>reserved</em></li>
<li>Ports numbered 1024 - 65535 are <em>open</em></li>
<li>Ports numbered 49152 - 65535 are generally considered <em>ephemeral</em></li>
</ul>
</div>
<div class="slide" id="the-tcp-ip-stack-application">
<h1>The TCP/IP Stack - Application</h1>
<p>The topmost layer is the 'Application Layer'</p>
<ul class="incremental simple">
<li>Deals directly with data produced or consumed by an application</li>
<li>Reads or writes data using a set of understood, well-defined <strong>protocols</strong><ul>
<li>HTTP, SMTP, FTP etc.</li>
</ul>
</li>
<li>Does not know (or need to know) about lower layer functionality<ul>
<li>The exception to this rule is <strong>endpoint</strong> data (or IP:Port)</li>
</ul>
</li>
</ul>
</div>
<div class="slide" id="id10">
<h1>The TCP/IP Stack - Application</h1>
<p class="big-centered">this is where we live and work</p>
</div>
<div class="slide" id="sockets">
<h1>Sockets</h1>
<p>Think back for a second to what we just finished discussing, the TCP/IP stack.</p>
<ul class="incremental simple">
<li>The <em>Internet</em> layer gives us an <strong>IP Address</strong></li>
<li>The <em>Transport</em> layer establishes the idea of a <strong>port</strong>.</li>
<li>The <em>Application</em> layer doesn't care about what happens below...</li>
<li><em>Except for</em> <strong>endpoint data</strong> (IP:Port)</li>
</ul>
<p class="incremental">A <strong>Socket</strong> is the software representation of that endpoint.</p>
<p class="incremental">Opening a <strong>socket</strong> creates a kind of transceiver that can send and/or
receive data at a given IP address and Port.</p>
</div>
<div class="slide" id="sockets-in-python">
<h1>Sockets in Python</h1>
<p>Python provides a standard library module which provides socket functionality.
It is called <strong>socket</strong>. Let's spend a few minutes getting to know this
module.</p>
<p>We're going to do this next part together, so open up a terminal and start
python.</p>
</div>
<div class="slide" id="id11">
<h1>Sockets in Python</h1>
<p>The sockets library provides tools for finding out information about hosts on
the network. For example, you can find out about the machine you are currently
using:</p>
<pre class="literal-block">
>>> import socket
>>> socket.gethostname()
'heffalump.local'
>>> socket.gethostbyname(socket.gethostname())
'10.211.55.2'
>>> socket.gethostbyname_ex(socket.gethosthame())
('heffalump.local', [], ['10.211.55.2', '10.37.129.2', '192.168.1.102'])
</pre>
</div>
<div class="slide" id="id12">
<h1>Sockets in Python</h1>
<p>You can also find out about machines that are located elsewhere, for example:</p>
<pre class="literal-block">
>>> socket.gethostbyname_ex('google.com')
('google.com', [], ['173.194.33.9', '173.194.33.14',
...
'173.194.33.6', '173.194.33.7',
'173.194.33.8'])
>>> socket.gethostbyname_ex('www.rad.washington.edu')
('elladan.rad.washington.edu', # <- canonical hostname
['www.rad.washington.edu'], # <- any aliases
['128.95.247.84']) # <- all active IP addresses
</pre>
</div>
<div class="slide" id="id13">
<h1>Sockets in Python</h1>
<p>To create a socket, you use the <strong>socket</strong> method of the <tt class="docutils literal">socket</tt> library:</p>
<pre class="literal-block">
>>> foo = socket.socket()
>>> foo
<socket._socketobject object at 0x10046cec0>
</pre>
</div>
<div class="slide" id="id14">
<h1>Sockets in Python</h1>
<p>A socket has some properties that are immediately important to us. These
include the <em>family</em>, <em>type</em> and <em>protocol</em> of the socket:</p>
<pre class="literal-block">
>>> foo.family
2
>>> foo.type
1
>>> foo.proto
0
</pre>
</div>
<div class="slide" id="socket-families">
<h1>Socket Families</h1>
<p>Think back a moment to our discussion of the <em>Internet</em> layer of the TCP/IP
stack. There were a couple of different types of IP addresses:</p>
<ul class="incremental simple">
<li>IPv4 ('192.168.1.100')</li>
<li>IPv6 ('2001:0db8:85a3:0042:0000:8a2e:0370:7334')</li>
</ul>
<p class="incremental">The <em>family</em> of a socket corresponds to the type of address you use to make a
connection to it.</p>
</div>
<div class="slide" id="a-quick-utility-method">
<h1>A quick utility method</h1>
<p>Let's explore these families for a moment. To do so, we're going to define
a method we can use to read contstants from the <tt class="docutils literal">socket</tt> library. It will
take a single argument, the shared prefix for a defined set of constants:</p>
<pre class="literal-block">
>>> def get_constants(prefix):
... """mapping of socket module constants to their names."""
... return dict( (getattr(socket, n), n)
... for n in dir(socket)
... if n.startswith(prefix)
... )
...
>>>
</pre>
</div>
<div class="slide" id="id15">
<h1>Socket Families</h1>
<p>Families defined in the <tt class="docutils literal">socket</tt> library are prefixed by <tt class="docutils literal">AF_</tt>:</p>
<pre class="literal-block">
>>> families = get_constants('AF_')
>>> families
{0: 'AF_UNSPEC', 1: 'AF_UNIX', 2: 'AF_INET',
11: 'AF_SNA', 12: 'AF_DECnet', 16: 'AF_APPLETALK',
17: 'AF_ROUTE', 23: 'AF_IPX', 30: 'AF_INET6'}
</pre>
<p class="small incremental"><em>Your results may vary</em></p>
<p class="incremental">Of all of these, the ones we care most about are <tt class="docutils literal">2</tt> (IPv4) and <tt class="docutils literal">30</tt> (IPv6).</p>
</div>
<div class="slide" id="unix-domain-sockets">
<h1>Unix Domain Sockets</h1>
<p>When you are on a machine with an operating system that is Unix-like, you will
find another generally useful socket family: <tt class="docutils literal">AF_UNIX</tt>, or Unix Domain
Sockets. Sockets in this family:</p>
<ul class="incremental simple">
<li>connect processes <strong>on the same machine</strong></li>
<li>are generally a bit slower than IPC connnections</li>
<li>have the benefit of allowing the same API for programs that might run on one
machine __or__ across the network</li>
<li>use an 'address' that looks like a pathname ('/tmp/foo.sock')</li>
</ul>
</div>
<div class="slide" id="id16">
<h1>Socket Families</h1>
<p>What is the <em>default</em> family for the socket we created just a moment ago?</p>
<p class="incremental">(remember we bound the socket to the symbol <tt class="docutils literal">foo</tt>)</p>
</div>
<div class="slide" id="socket-types">
<h1>Socket Types</h1>
<p>The socket type determines how the socket handles connections. Socket type
constants defined in the <tt class="docutils literal">socket</tt> library are prefixed by <tt class="docutils literal">SOCK_</tt>:</p>
<pre class="literal-block">
>>> types = get_constants('SOCK_')
>>> types
{1: 'SOCK_STREAM', 2: 'SOCK_DGRAM',
...}
</pre>
<p class="incremental">In general, the only two of these that are widely useful are <tt class="docutils literal">1</tt>
(representing TCP type connections) and <tt class="docutils literal">2</tt> (representing UDP type
connections).</p>
</div>
<div class="slide" id="id17">
<h1>Socket Types</h1>
<p>What is the <em>default</em> type for our generic socket, <tt class="docutils literal">foo</tt>?</p>
</div>
<div class="slide" id="socket-protocols">
<h1>Socket Protocols</h1>
<p>A socket also has a designated <em>protocol</em>. The constants for these are
prefixed by <tt class="docutils literal">IPPROTO</tt>:</p>
<pre class="literal-block">
>>> protocols = get_constants('IPPROTO_')
>>> protocols
{0: 'IPPROTO_IP', 1: 'IPPROTO_ICMP',
...,
255: 'IPPROTO_RAW'}
</pre>
<p class="incremental">The choice of which protocol to use for a socket is determined by the type of
activity the socket is intended to support. What messages are you needing to
send?</p>
</div>
<div class="slide" id="id18">
<h1>Socket Protocols</h1>
<p>What is the <em>default</em> protocol used by our generic socket, <tt class="docutils literal">foo</tt>?</p>
</div>
<div class="slide" id="address-information">
<h1>Address Information</h1>
<p>When creating a socket, you can provide <tt class="docutils literal">family</tt>, <tt class="docutils literal">type</tt> and <tt class="docutils literal">protocol</tt>
as arguments to the constructor:</p>
<pre class="literal-block">
>>> bar = socket.socket(socket.AF_INET,
... socket.SOCK_STREAM,
... socket.IPPROTO_IP)
...
>>> bar
<socket._socketobject object at 0x1005b8b40>
</pre>
</div>
<div class="slide" id="id19">
<h1>Address Information</h1>
<p>But how do you find out the <em>right</em> values?</p>
<p class="incremental">You ask.</p>
</div>
<div class="slide" id="id20">
<h1>A quick utility method</h1>
<p>Create the following function:</p>
<pre class="literal-block">
>>> def get_address_info(host, port):
... for response in socket.getaddrinfo(host, port):
... fam, typ, pro, nam, add = response
... print 'family: ', families[fam]
... print 'type: ', types[typ]
... print 'protocol: ', protocols[pro]
... print 'canonical name: ', nam
... print 'socket address: ', add
... print
...
>>>
</pre>
</div>
<div class="slide" id="on-your-own-machine">
<h1>On Your Own Machine</h1>
<p>Now, ask your own machine what services are available on 'http':</p>
<pre class="literal-block">
>>> get_address_info(socket.gethostname(), 'http')
family: AF_INET
type: SOCK_DGRAM
protocol: IPPROTO_UDP
canonical name:
socket address: ('10.211.55.2', 80)
family: AF_INET
...
>>>
</pre>
<p class="incremental">What answers do you get?</p>
</div>
<div class="slide" id="on-the-internet">
<h1>On the Internet</h1>
<pre class="literal-block">
>>> get_address_info('www.google.com', 'http')
family: AF_INET
type: SOCK_STREAM
protocol: IPPROTO_TCP
canonical name:
socket address: ('74.125.129.105', 80)
family: AF_INET
...
>>>
</pre>
<p class="incremental">Try a few other servers you know about.</p>
</div>
<div class="slide" id="first-steps">
<h1>First Steps</h1>
<p class="big-centered">Let's put this to use</p>
</div>
<div class="slide" id="client-connections">
<h1>Client Connections</h1>
<p>The information returned by a call to <tt class="docutils literal">socket.getaddrinfo</tt> is all you need
to make a proper connection to a socket on a remote host. The value returned
is a tuple of</p>
<ul class="incremental simple">
<li>socket family</li>
<li>socket type</li>
<li>socket protocol</li>
<li>canonical name</li>
<li>socket address</li>
</ul>
</div>
<div class="slide" id="construct-a-socket">
<h1>Construct a Socket</h1>
<p>We've already made a socket <tt class="docutils literal">foo</tt> using the generic constructor without any
arguments. We can make a better one now by using real address information from
a real server online:</p>
<pre class="literal-block">
>>> all = socket.getaddrinfo('www.google.com', 'http')
>>> info = all[0]
>>> info
(2, 1, 6, '', ('173.194.79.104', 80))
>>> google_socket = socket.socket(*info[:3])
</pre>
</div>
<div class="slide" id="connecting-a-socket">
<h1>Connecting a Socket</h1>
<p>Once the socket is constructed with the appropriate <em>family</em>, <em>type</em> and
<em>protocol</em>, we can connect it to the address of our remote server:</p>
<pre class="literal-block">
>>> google_socket.connect(info[-1])
>>>
</pre>
<ul class="incremental simple">
<li>a successful connection returns <tt class="docutils literal">None</tt></li>
<li>a failed connection raises an error</li>
<li>you can use the <em>type</em> of error returned to tell why the connection failed.</li>
</ul>
</div>
<div class="slide" id="sending-a-message">
<h1>Sending a Message</h1>
<p>We can send a message to the server on the other end of our connection:</p>
<pre class="literal-block">
>>> msg = "GET / HTTP/1.1\r\n\r\n"
>>> google_socket.sendall(msg)
>>>
</pre>
<ul class="incremental simple">
<li>the transmission continues until all data is sent or an error occurs</li>
<li>success returns <tt class="docutils literal">None</tt></li>
<li>failure to send raises an error</li>
<li>you can use the type of error to figure out why the transmission failed</li>
<li>you cannot know how much, if any, of your data was sent</li>
</ul>
</div>
<div class="slide" id="receiving-an-reply">
<h1>Receiving an Reply</h1>
<p>Whatever reply we get is received by the socket we created. We can read it
back out:</p>
<pre class="literal-block">
>>> response = google_socket.recv(4096)
>>> response
'HTTP/1.1 200 OK\r\nDate: Thu, 03 Jan 2013 05:56:53
...
</pre>
<ul class="incremental simple">
<li>The sole required argument is a buffer size, it should be a power of 2 and
smallish</li>
<li>the returned value will be a string of buffer size (or smaller if less data
was received)</li>
</ul>
</div>
<div class="slide" id="cleaning-up">
<h1>Cleaning Up</h1>
<p>When you are finished with a connection, you should always close it:</p>
<pre class="literal-block">
>>> google_socket.close()
</pre>
</div>
<div class="slide" id="putting-it-all-together">
<h1>Putting it all together</h1>
<pre class="literal-block">
>>> all = socket.getaddrinfo('google.com', 'http')
>>> info = all[0]
>>> gs = socket.socket(*info[:3])
>>> gs.connect(info[-1])
>>> msg = "GET / HTTP/1.1\r\n\r\n"
>>> gs.sendall(msg)
>>> response = gs.recv(4096)
>>> response
... 'HTTP/1.1 200 OK\r\n...
>>> gs.close()
</pre>
</div>
<div class="slide" id="server-side">
<h1>Server Side</h1>
<p class="big-centered">What about the other half of the equation?</p>
</div>
<div class="slide" id="id21">
<h1>Construct a Socket</h1>
<p>For the moment, stop typing this into your interpreter.</p>
<p>Again, we begin by constructing a socket. Since we are actually the server
this time, we get to choose family, type and protocol:</p>
<pre class="literal-block">
>>> server_socket = socket.socket(
... socket.AF_INET,
... socket.SOCK_STREAM,
... socket.IPPROTO_IP)
...
>>> server_socket
<socket._socketobject object at 0x100563c90>
</pre>
</div>
<div class="slide" id="bind-the-socket">
<h1>Bind the Socket</h1>
<p>Our server socket needs to be bound to an address. This is the IP Address and
Port to which clients must connect:</p>
<pre class="literal-block">
>>> address = ('127.0.0.1', 50000)
>>> server_socket.bind(address)
</pre>
</div>
<div class="slide" id="listen-for-connections">
<h1>Listen for Connections</h1>
<p>Once our socket is created, we use it to listen for attempted connections:</p>
<pre class="literal-block">
>>> server_socket.listen(1)
</pre>
<ul class="incremental simple">
<li>the argument to <tt class="docutils literal">listen</tt> is the <em>backlog</em></li>
<li>the <em>backlog</em> is the maximum number of connections that the socket will queue</li>
<li>once the limit is reached, the socket refuses new connections</li>
</ul>
</div>
<div class="slide" id="accept-incoming-messages">
<h1>Accept Incoming Messages</h1>
<p>When a socket is listening, it can receive incoming messages:</p>
<pre class="literal-block">
>>> connection, client_address = server_socket.accept()
... # note that nothing happens here until a client sends something
>>> connection.recv(16)
</pre>
<ul class="incremental simple">
<li>the <tt class="docutils literal">connection</tt> returned by a call to <tt class="docutils literal">accept</tt> is a <strong>new socket</strong></li>
<li>you do not need to know what port it uses, this is managed</li>
<li>the <tt class="docutils literal">client_address</tt> is a two-tuple of IP Address and Port (very familiar)</li>
<li><tt class="docutils literal">backlog</tt> represents the maximum number of <tt class="docutils literal">connection</tt> sockets that a
server can spin off</li>
<li>close a <tt class="docutils literal">connection</tt> socket to accept a new connection once the max is
reached</li>
</ul>
</div>
<div class="slide" id="send-a-reply">
<h1>Send a Reply</h1>
<p>You can use the <tt class="docutils literal">connection</tt> socket spun off by <tt class="docutils literal">accept</tt> to send a reply
back to the client socket:</p>
<pre class="literal-block">
>>> connection.sendall("messasge received")
</pre>
</div>
<div class="slide" id="clean-up">
<h1>Clean Up</h1>
<p>Once a transaction between the client and server is complete, the
<tt class="docutils literal">connection</tt> socket should be closed so that new connections can be made:</p>
<pre class="literal-block">
>>> connection.close()
</pre>
</div>
<div class="slide" id="id22">
<h1>Putting it all together</h1>
<p>Open a second terminal next to your first, and let's try out the full
connection:</p>
<img alt="img/socket_interaction.png" class="align-center" src="img/socket_interaction.png" style="width: 100%;" />
</div>
<div class="slide" id="lab-time">
<h1>Lab Time</h1>
<p>For our class lab time today, let's explore what we've learned. First, we'll
need the samples:</p>
<ul class="incremental simple">
<li>visit the class repository (<a class="reference external" href="http://github.com/cewing/training.python_web">http://github.com/cewing/training.python_web</a>)</li>
<li><a class="reference external" href="http://help.github.com/articles/fork-a-repo">create a fork</a> of the repository in your own git account</li>
<li>clone your fork to your local machine</li>
</ul>
</div>
<div class="slide" id="id23">
<h1>Lab Time</h1>
<p>In the repository you've just cloned, you'll find a directory called
<tt class="docutils literal">assignments</tt>. This is where all our class lab and take-home assignments
will be located.</p>
<ul class="incremental simple">
<li>Find <tt class="docutils literal">assignments/week01/lab</tt></li>
<li>Open <tt class="docutils literal">echo_server.py</tt> and <tt class="docutils literal">echo_client.py</tt></li>
<li>Using what you've learned today, complete the server and client by replacing
comments with real code</li>
<li>Start the server on your local machine, run the client and send some messages</li>
<li>If you complete that, then copy the server to your Blue Box VM. Run it
remotely and use the client to send it some messages</li>
<li>What do you have to change to make that work?</li>
</ul>
</div>
<div class="slide" id="assignment">
<h1>Assignment</h1>
<p>Using what you've learned, expand on the client/server relationship. Create a
server which accepts two numbers, adds them, and returns the result to the
client.</p>
</div>
<div class="slide" id="submitting-the-assignment">
<h1>Submitting the Assignment</h1>
<ul class="simple">
<li>Add <tt class="docutils literal">sum_server.py</tt> and <tt class="docutils literal">sum_client.py</tt> to the
<tt class="docutils literal">assignments/week01/athome/</tt> directory of your fork of the class
repository.</li>
<li>When you are satisfied with your code, <a class="reference external" href="http://help.github.com/articles/using-pull-requests">make a pull request</a></li>
<li>I should be able to run the server and client scripts on my local machine
and get results.</li>
<li>For bonus points, set the server running on your VM. I should be able to run
your client script from my local machine and get the expected reply.</li>
<li>Due by Sunday morning if you want me to review it :)</li>
</ul>
</div>
</div>
</body>
</html>