-
Notifications
You must be signed in to change notification settings - Fork 0
/
adventures-with-sockets-threads-and-more.html
389 lines (344 loc) · 20.3 KB
/
adventures-with-sockets-threads-and-more.html
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
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<!-- Set the viewport width to device width for mobile -->
<meta name="viewport" content="width=device-width" />
<title>Adventures with sockets, threads and more!</title>
<link rel="stylesheet" href="http://lmontopo.github.io/theme/css/normalize.css" />
<link rel="stylesheet" href="http://lmontopo.github.io/theme/css/foundation.min.css" />
<link rel="stylesheet" href="http://lmontopo.github.io/theme/css/style.css" />
<link rel="stylesheet" href="http://lmontopo.github.io/theme/css/pygments.css" />
<script src="http://lmontopo.github.io/theme/js/modernizr.js"></script>
</head>
<body>
<!-- Nav Bar -->
<nav>
<div class="top-bar">
<div class="row">
<div class="large-9 large-centered columns">
<h1><a href="http://lmontopo.github.io">The L Blog</a></h1>
</div>
</div>
</div>
<!-- Show menu items and pages -->
<div class="row">
<div class="large-9 columns">
<ul class="button-group navigation">
</ul>
</div>
</div>
</nav>
<!-- End Nav -->
<!-- Main Page Content and Sidebar -->
<div class="row">
<!-- Main Blog Content -->
<div class="large-9 columns">
<article>
<header>
<h3 class="article-title"><a href="http://lmontopo.github.io/adventures-with-sockets-threads-and-more.html" rel="bookmark"
title="Permalink to Adventures with sockets, threads and more!">Adventures with sockets, threads and more!</a></h3>
</header>
<h6 class="subheader" title="2014-11-11T00:00:00-05:00">Tue 11 November 2014
</h6>
<p>For a while now I've wanted to learn more about the internet, about
servers, and about how web apps <em>really</em> work. Last week I finished a
small flaks tutorial. I enjoyed the tutorial and I learned some cool
things by doing it, yet, I was feeling unsatisfied. The tutorial just
didn't hit the spot for me. I wasn't really sure what I was after, but I
knew it was something deeper. Yesterday I discovered sockets, and it was
dead on!</p>
<p>This blog post is going to be a (not so) little write up of some things
I've learned as I digging around in the world of sockets and other
networky type things. I'll start with a few questions I was thinking
about yesterday. I'll provide what I think are some decent and mostly
true answers to these questions. (Of course, if you find something in
this post that is just outright wrong, please do reach out to correct
me!). Then I'll introduce some code Susan and I wrote to make a simple
web chat service using sockets. Finally, a second round of questions and
answers will be presented. Enjoy!</p>
<h4>QUESTIONS ROUND 1</h4>
<h5>What's a socket?</h5>
<p>This is a question I've spent a great deal of time trying to answer.
Here's the answer I've settled on: A socket is some sort of abstract
object like that of a "file" on your computer. We could say that the
object type "socket" is built into the operating system of our computer
and allows users (or programs) to create instances of them at will.
Sockets are used as the endpoints of any bidirectional communication
channel. The socket contains the FROM IP address, the TO IP address, the
FROM port number, and the TO port
number.<sup id="fnref:1"><a class="footnote-ref" href="#fn:1" rel="footnote">1</a></sup> We can think about the function of sockets to be like plugging chords
into walls on the two ends of your communcation channel.</p>
<h5>How does my computer communicate with my router?</h5>
<p>The short answer: via radio signals. Modern computers come with a built
in wireless adapter which translates data from your computer into radio
waves. These radio waves can then be sent out into the world and picked
up by a router. Communication can occur in the other direction as well:
The router can send radio waves to a comptuer and the computer will
translate those waves into 0s and 1s so that it can understand the
message. One thing that I found interesting is that my computer is
always listening to the router. Sometimes my computer will hear messages
that aren't even addressed to it, in which case it won't accept these
messages. So there's a difference between "listening" and "accepting"
messages from the router. We'll come back to this!</p>
<h5>Can older computers connect to the internet?</h5>
<p>It depends. If your computer has the necessary internet handling
software but is simply lacking a translater, then yes. The modem,
afterall, is simply a translator. It takes signals (probably passed to
it through your phone line) and transforms these messages into 0s and 1s
that your computer can understand. But, this only makes your computer
internet ready if you're operating system can create sockets, and can
understand and work with internet protocols. Otherwise, extra software
would have to be implimented and I'm not exactly sure if this can always
be done.</p>
<h5>SOME CODE</h5>
<p>To learn more about sockets Susan and I implimented a chat service
between our two computers using sockets. I wrote the code for the
"server", and she wrote the code for the "client". If I ran 'server' on
my computer and then she ran 'client' on hers, we were able to chat back
and forth in our terminals! Anything I wrote in my terminal would be
sent to hers the moment I pressed enter. Likewise, messages she typed in
her terminal would be sent to mine when she pressed enter. It was like a
real world chat service! Here's our code:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="c">###SERVER (On Leta's Computer)</span>
<span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">threading</span>
<span class="n">serversocket</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">()</span>
<span class="c">#host = socket.gethostname()</span>
<span class="n">port</span> <span class="o">=</span> <span class="mi">9999</span>
<span class="n">serversocket</span><span class="o">.</span><span class="n">setsockopt</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">SOL_SOCKET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SO_REUSEADDR</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">serversocket</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="s">"10.0.7.65"</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="c"># queue up to 5 requests:</span>
<span class="n">serversocket</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="n">clientsocket</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">serversocket</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">listen</span><span class="p">(</span><span class="n">connection</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">clientsocket</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'friend says'</span><span class="p">,</span> <span class="n">msg</span>
<span class="k">def</span> <span class="nf">write</span><span class="p">(</span><span class="n">connection</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">message</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">''</span><span class="p">)</span>
<span class="n">clientsocket</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s">'HTTP/1.0 200 OK</span><span class="se">\n\n</span><span class="s">'</span><span class="p">)</span>
<span class="n">clientsocket</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
<span class="n">clientsocket</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span> <span class="o">=</span> <span class="n">write</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">clientsocket</span><span class="p">])</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span> <span class="o">=</span> <span class="n">listen</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">clientsocket</span><span class="p">])</span>
<span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="n">r</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</pre></div>
</td></tr></table>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="c">#CLIENT (on Susan's computer)import socket</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">threading</span>
<span class="k">def</span> <span class="nf">server</span><span class="p">():</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="n">HOST</span><span class="o">=</span> <span class="s">''</span>
<span class="n">SOCKET_LIST</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">RECV_BUFFER</span> <span class="o">=</span> <span class="mi">4096</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="mi">9999</span>
<span class="n">server_addr</span> <span class="o">=</span> <span class="p">(</span><span class="s">"10.0.7.65"</span><span class="p">,</span> <span class="n">PORT</span><span class="p">)</span>
<span class="k">print</span> <span class="o">>></span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">'connecting to </span><span class="si">%s</span><span class="s"> port </span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="n">server_addr</span>
<span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">server_addr</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">t</span><span class="o">=</span><span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">send</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">[</span><span class="n">sock</span><span class="p">])</span>
<span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">print</span> <span class="s">"hi!!!! TESTING!!"</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="n">RECV_BUFFER</span><span class="p">)</span>
<span class="k">print</span> <span class="o">>></span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">'Leta says: </span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="n">data</span>
<span class="k">finally</span><span class="p">:</span>
<span class="k">print</span> <span class="o">>></span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">'closing socket'</span>
<span class="n">sock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</td></tr></table>
<h4>QUESTIONS ROUND 2</h4>
<h5>What is happening when I write "socket.listen"?</h5>
<p>As mentioned earlier, your computer is constantly "listening" to
messages from your router. But its not necessarily ACCEPTING them.
Calling socket.listen() tells your computer to actively start accepting
messages that are addressed to the socket. So, as soon as my computer
sees some message addressed to a socket which has been told to listen,
the socket will send back a message saying something like, "OK, I am
willing to receive your message". And then the message will be sent and
received. (At least I think thats kind of how it goes.)</p>
<h5>What is TCP? What is IP? Are they related?</h5>
<p>TCP stands for Transmission Control Protocoll. IP stands for Internet
Protocol. Both are "protcols" in the sense that they outline the
standards by which machines are supposed to communicate with each other.
To see how they differ, lets walk through how Susan's and my computer
are dealing with our 'chat server'. Suppose I send the message "hello"
to Susan. When I send this message to Susan the string "hello" will be
wrappred with extra data necessary to satisfy TCP. Once this mesage
satisfies TCP it can be sent to my operating system, which will look at
it, realize that data needs to be sent out in the world, and will
package the data with yet another layer so it adheres to IP. This
message is then translated to radio waves to be sent to the router. Upon
receiving my message the router will pass the package to Susan's
computer. When Susan's computer receives the package it translates the
data back into 0s and 1s and then begins unpacking it. Her operating
system will take off the outtermost layer of packaging: that associated
with IP. Her computer will find that the contents of this package adhere
to TCP. Susan's computer will make sure that TCP is followed. Since TCP
is a protocol which ensures that messages are sent in order, this means
that within the TCP packaging Susan's computer might find some data that
says "Hey! I'm packet number 13 sent from Leta's computer to yours. Have
you gotten package 1 through 12 already? You can't open me up until
you've received all the ones that come before." And her computer will
respond saying something like "Yes, I have gotten all the messages that
come before, so I can now open you up". Susan's computer will then pass
the package to the application (the chat service) which will unpack the
data to find the message I sent: "hello".</p>
<p>I know this is pretty confusing. I'm still wrestling with these concepts
myself. Lets recap: On the senders side, the package gets wrapped with
all sorts of layers and then this package gets passed around, and on the
receivers side, the package gets unpacked layer by layer. Each layer is
associated with another protocol. Underneath the IP packaging, data can
be sent adhering to TCP or adhering to other protocols. Indeed, TCP is
not the only one. As I mentioned above, TCP is a protocol that ensures
that data is sent in a particular order, and it ensures that a response
be sent back to the sender to communicate if/when the data was received.
Another protocol is UDP: User Datagram Protocol. It does not ensure that
delivery has occured and does not ensure that messages are delivered in
order. We're not going to get into why UDP might be used over TCP, but
the point I wanted to make was that IP can encapsulate many different
types of messages. TCP is just the one that happened to be used in the
chat server Susan and I implimented.</p>
<h5>What is a thread?</h5>
<p>Have you ever heard the term "multi-threaded programming" and wondered
what the heck people were talking about? If so, read on! Consider a chat
server where I could type a message to Susan, and then I couldn't type
one again until I had her response. That would kind of suck, wouldn't
it? So what this means is that in a good chat service, my server can be
waiting for me (the user) to input a message, and can simultaneously be
listening for any incoming messages from Susan. The key here is that we
want our program to be doing <strong>two things simultaneously</strong>. Looking at
the code for Server, above, we see that what I want is for the function
"write" and the function "listen" to be running concurrently. And the
way I implemented this was through threads. Each thread refers to a
different task that we want to be carried out, and threading is the
process of running them simultaneously. Conclusion: Threading rocks!</p>
<h5>Are sockets being used when I use my browser to visit a webpage?</h5>
<p>YES! Often multiple sockets are used to transfer the information of one
a single webpage to your computer. Generally speaking, each HTTP request
has its own socket that it connects with. This socket will close as soon
as the request has been made and received. Some web pages have 100s of
GET or POST (or other) HTTP requests. This means that 100s of sockets
will be created, opened, and closed on my computer in the short time it
takes to load the webpage in my browser. I have been told that this is
actually starting to change. I don't know very mucha about this, but I
think HTTP is starting to allow a single socket to handle more than one
HTTP requests.</p>
<div class="footnote">
<hr />
<ol>
<li id="fn:1">
<p>A Port is just this idea that we've implimented on our computers so
that we can have several things going on on one computer. Its kind
of like apartments on an apartment building. If we have to have
several separate things going on at different addresses within the
same machine, ports is the way we've done
that.  <a class="footnote-backref" href="#fnref:1" rev="footnote" title="Jump back to footnote 1 in the text">↩</a></p>
</li>
</ol>
</div>
<p class="subheader">Category: <a href="http://lmontopo.github.io/category/blog.html">Blog</a>
Tagged:
<a href="http://lmontopo.github.io/tag/web.html">Web </a>
<a href="http://lmontopo.github.io/tag/threading.html">Threading </a>
</p>
</article>
</div>
<!-- End Main Content -->
<!-- Sidebar -->
<aside class="large-3 columns">
<h5 class="sidebar-title">Site</h5>
<ul class="side-nav">
<li><a href="http://lmontopo.github.io/archives.html">Archives</a>
<li><a href="http://lmontopo.github.io/tags.html">Tags</a>
</ul>
<h5 class="sidebar-title">Categories</h5>
<ul class="side-nav">
<li><a href="http://lmontopo.github.io/category/about.html">About</a></li>
<li><a href="http://lmontopo.github.io/category/blog.html">Blog</a></li>
</ul>
</aside> <!-- End Sidebar -->
</div> <!-- End Main Content and Sidebar -->
<!-- Footer -->
<footer class="row">
<div class="large-12 columns">
<hr />
<div class="row">
<div class="large-6 columns">
<!-- <p>The L Blog by Leta Montopoli</p> -->
</div>
</div>
</div>
</footer>
</body>
</html>