📄 proxy_lab.htm
字号:
<p class=MsoNormal align=left style='text-align:left;mso-layout-grid-align:
none;text-autospace:none'><b><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'><o:p> </o:p></span></b></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;text-align:left;
text-indent:-21.0pt;mso-list:l2 level1 lfo2;tab-stops:list 21.0pt;mso-layout-grid-align:
none;text-autospace:none'><![if !supportLists]><span lang=EN-US
style='font-size:12.0pt;font-family:Wingdings;mso-fareast-font-family:Wingdings;
mso-bidi-font-family:Wingdings;mso-font-kerning:0pt'><span style='mso-list:
Ignore'>l<span style='font:7.0pt "Times New Roman"'>
</span></span></span><![endif]><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'>Test your proxy with a real browser! Explore the browser
settings until you find “proxies”, <span class=GramE>then</span> enter the host
and port where you’re running yours. With Netscape, choose Edit, then
Preferences, then Advanced, then Proxies, then Manual Proxy Configuration. In
Internet Explorer, choose Tools, then Options, then Connections, then LAN
Settings. Check ’Use proxy server,’ and click Advanced. Just set your HTTP
proxy, ’cause that’s all your code is going to be able to handle.<o:p></o:p></span></p>
<p class=MsoNormal align=left style='text-align:left;mso-layout-grid-align:
none;text-autospace:none'><span lang=EN-US style='font-size:12.0pt;mso-font-kerning:
0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;text-align:left;
text-indent:-21.0pt;mso-list:l2 level1 lfo2;tab-stops:list 21.0pt;mso-layout-grid-align:
none;text-autospace:none'><![if !supportLists]><span lang=EN-US
style='font-size:12.0pt;font-family:Wingdings;mso-fareast-font-family:Wingdings;
mso-bidi-font-family:Wingdings;mso-font-kerning:0pt'><span style='mso-list:
Ignore'>l<span style='font:7.0pt "Times New Roman"'>
</span></span></span><![endif]><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'>For an example of a real, working web server in only 282
lines of source code, we are providing tiny, a minimal server written by Dave <span
class=SpellE>O’Hallaron</span>. Of course, you can (and should) test your proxy
on real web sites, but tiny can give you a more controlled environment, as well
as an excellent example of server-side socket programming and HTTP processing.<o:p></o:p></span></p>
<p class=MsoNormal align=left style='text-align:left;mso-layout-grid-align:
none;text-autospace:none'><span lang=EN-US style='font-size:12.0pt;mso-font-kerning:
0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;text-align:left;
text-indent:-21.0pt;mso-list:l2 level1 lfo2;tab-stops:list 21.0pt;mso-layout-grid-align:
none;text-autospace:none'><![if !supportLists]><span lang=EN-US
style='font-family:Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:
Wingdings;mso-font-kerning:0pt'><span style='mso-list:Ignore'>l<span
style='font:7.0pt "Times New Roman"'>
</span></span></span><![endif]><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'>In certain cases, a client closing a connection
prematurely results in a SIGPIPE signal. This is particularly the case with
Internet Explorer. To prevent your proxy from crashing, you should ignore this
signal by adding this early in your code: </span><span lang=EN-US
style='font-family:"Courier New";mso-font-kerning:0pt'>signal(SIGPIPE, SIG
IGN);<o:p></o:p></span></p>
<p class=MsoNormal align=left style='text-align:left;mso-layout-grid-align:
none;text-autospace:none'><span lang=EN-US style='font-size:12.0pt;mso-font-kerning:
0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;text-align:left;
text-indent:-21.0pt;mso-list:l2 level1 lfo2;tab-stops:list 21.0pt;mso-layout-grid-align:
none;text-autospace:none'><![if !supportLists]><span lang=EN-US
style='font-size:12.0pt;font-family:Wingdings;mso-fareast-font-family:Wingdings;
mso-bidi-font-family:Wingdings;mso-font-kerning:0pt'><span style='mso-list:
Ignore'>l<span style='font:7.0pt "Times New Roman"'>
</span></span></span><![endif]><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'>To test how your proxy handles requests under high
concurrency, try accessing the following web sites from your proxy with
Internet Explorer:<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>http://www.nfl.com/<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>http://www.cnn.com/<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>http://www.weather.com/<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>The IE would set up
tens of concurrent connections with your proxy.<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;text-align:left;
text-indent:-21.0pt;mso-list:l1 level1 lfo3;tab-stops:list 21.0pt;mso-layout-grid-align:
none;text-autospace:none'><![if !supportLists]><span lang=EN-US
style='font-size:12.0pt;font-family:Wingdings;mso-fareast-font-family:Wingdings;
mso-bidi-font-family:Wingdings;mso-font-kerning:0pt'><span style='mso-list:
Ignore'>l<span style='font:7.0pt "Times New Roman"'>
</span></span></span><![endif]><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'>Getting all the details right in socket programming is a
pain. I recommend looking at examples (such as tiny and reverse telnet).
However, I <i>strongly </i>recommend <i>not </i>just cutting and pasting code–
use the examples to figure out what’s going on and what you’re supposed to do. <span
class=SpellE><span class=GramE>csapp.c</span></span> has provided useful
wrapper functions as listed in the book.<o:p></o:p></span></p>
<p class=MsoNormal align=left style='text-align:left;mso-layout-grid-align:
none;text-autospace:none'><span lang=EN-US style='font-size:12.0pt;mso-font-kerning:
0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>Here’s a quick
reference on how to set up a server socket to listen for connections (this is
just a summary; you’ll need to dig deeper in the example code and man pages for
more details):<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>1. Obtain a socket
with the <span class=GramE>socket(</span>2) system call.<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>2. Helpful, but not
necessary: set the SO_REUSEADDR option on the socket.<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:33.0pt;mso-para-margin-left:
2.0gd;text-align:left;text-indent:-12.0pt;mso-char-indent-count:-1.0;
mso-layout-grid-align:none;text-autospace:none'><span lang=EN-US
style='font-size:12.0pt;mso-font-kerning:0pt'>3. Bind it to an address with <span
class=GramE>bind(</span>2). This requires properly setting up a <span
class=SpellE>sockaddr</span> in structure. Set the sin family to AF_INET (to
get a regular network socket), the <br>
sin _<span class=SpellE>addr.s_addr</span> to INADDR_ANY (to have the system
fill in the default IP address), and the sin port to the desired port. Don’t
forget that this stuff is in network byte order!<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:33.0pt;mso-para-margin-left:
2.0gd;text-align:left;text-indent:-12.0pt;mso-char-indent-count:-1.0;
mso-layout-grid-align:none;text-autospace:none'><span lang=EN-US
style='font-size:12.0pt;mso-font-kerning:0pt'>4. Set the socket up to listen
for connections with <span class=GramE>listen(</span>2). <o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:33.0pt;mso-para-margin-left:
2.0gd;text-align:left;text-indent:-12.0pt;mso-char-indent-count:-1.0;
mso-layout-grid-align:none;text-autospace:none'><span lang=EN-US
style='font-size:12.0pt;mso-font-kerning:0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:33.0pt;mso-para-margin-left:
2.0gd;text-align:left;text-indent:-12.0pt;mso-char-indent-count:-1.0;
mso-layout-grid-align:none;text-autospace:none'><span lang=EN-US
style='font-size:12.0pt;mso-font-kerning:0pt'>When a connection is ready, you
can accept with <span class=GramE>accept(</span>2).<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>On the client side,
the process of connecting to a server (given the hostname and port number) is a
little bit easier:<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>1. Obtain a socket
with <span class=GramE>socket(</span>2).<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;mso-para-margin-left:
2.0gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'>2. Lookup the host
entry of the host with <span class=SpellE><span class=GramE>gethostbyname</span></span><span
class=GramE>(</span>2).<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:33.0pt;mso-para-margin-left:
2.0gd;text-align:left;text-indent:-12.0pt;mso-char-indent-count:-1.0;
mso-layout-grid-align:none;text-autospace:none'><span lang=EN-US
style='font-size:12.0pt;mso-font-kerning:0pt'>3. Use <span class=GramE>connect(</span>2)
to actually connect to the server. Again, this requires filling out a <span
class=SpellE>sockaddr</span> in <span class=SpellE>struct</span>. Use AF_INET
for the sin family, and copy the <span class=SpellE>sin_addr</span> directly
from the <span class=SpellE>h_addr</span> field of the <span class=SpellE>struct</span>
<span class=SpellE>hostent</span> returned by <span class=SpellE>gethostbyname</span>.
You can figure out how to set the port.<o:p></o:p></span></p>
<p class=MsoNormal align=left style='margin-left:11.95pt;mso-para-margin-left:
1.14gd;text-align:left;mso-layout-grid-align:none;text-autospace:none'><span
lang=EN-US style='font-size:12.0pt;mso-font-kerning:0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;text-align:left;
text-indent:-21.0pt;mso-list:l1 level1 lfo3;tab-stops:list 21.0pt;mso-layout-grid-align:
none;text-autospace:none'><![if !supportLists]><span lang=EN-US
style='font-size:12.0pt;font-family:Wingdings;mso-fareast-font-family:Wingdings;
mso-bidi-font-family:Wingdings;mso-font-kerning:0pt'><span style='mso-list:
Ignore'>l<span style='font:7.0pt "Times New Roman"'>
</span></span></span><![endif]><b><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'>IMPORTANT: </span></b><span lang=EN-US style='font-size:
12.0pt;mso-font-kerning:0pt'>If you use threads to handle connection requests,
you must run them as <i>detached</i>, not <i>joinable</i>, to avoid memory
leaks. To run a thread detached, add the line <span class=SpellE>Pthread_<span
class=GramE>detach</span></span><span class=GramE>(</span>thread id) in the
parent after calling <span class=SpellE>Pthread_create</span>().<o:p></o:p></span></p>
<p class=MsoNormal align=left style='text-align:left;mso-layout-grid-align:
none;text-autospace:none'><span lang=EN-US style='font-size:12.0pt;mso-font-kerning:
0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;text-align:left;
text-indent:-21.0pt;mso-list:l1 level1 lfo3;tab-stops:list 21.0pt;mso-layout-grid-align:
none;text-autospace:none'><![if !supportLists]><span lang=EN-US
style='font-size:12.0pt;font-family:Wingdings;mso-fareast-font-family:Wingdings;
mso-bidi-font-family:Wingdings;mso-font-kerning:0pt'><span style='mso-list:
Ignore'>l<span style='font:7.0pt "Times New Roman"'>
</span></span></span><![endif]><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'>In general, use the man pages for documentation on system
calls. Man pages should always be your first line of defense, but unfortunately
they are not adequate in themselves. For excellent in-depth explanations of
network programming, <span class=GramE>select(</span>2), and threaded servers,
see W. Richard Stevens, “Unix Network Programming: Networking APIs (Second
Edition), Prentice-Hall, 1998.<o:p></o:p></span></p>
<p class=MsoNormal align=left style='text-align:left;mso-layout-grid-align:
none;text-autospace:none'><span lang=EN-US style='font-size:12.0pt;mso-font-kerning:
0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;text-align:left;
text-indent:-21.0pt;mso-list:l1 level1 lfo3;tab-stops:list 21.0pt;mso-layout-grid-align:
none;text-autospace:none'><![if !supportLists]><span lang=EN-US
style='font-size:12.0pt;font-family:Wingdings;mso-fareast-font-family:Wingdings;
mso-bidi-font-family:Wingdings;mso-font-kerning:0pt'><span style='mso-list:
Ignore'>l<span style='font:7.0pt "Times New Roman"'>
</span></span></span><![endif]><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'>Random hint: Don’t mix buffered and un-buffered
reads/writes on a socket. Examples of buffered I/O: <span class=SpellE><span
class=GramE>fprintf</span></span><span class=GramE>(</span>3), <span
class=SpellE>fscanf</span>(3). Examples of un-buffered I/O: <span class=GramE>write(</span>2),
read(2).<o:p></o:p></span></p>
<p class=MsoNormal align=left style='text-align:left;mso-layout-grid-align:
none;text-autospace:none'><span lang=EN-US style='font-size:12.0pt;mso-font-kerning:
0pt'><o:p> </o:p></span></p>
<p class=MsoNormal align=left style='margin-left:21.0pt;text-align:left;
text-indent:-21.0pt;mso-list:l1 level1 lfo3;tab-stops:list 21.0pt;mso-layout-grid-align:
none;text-autospace:none'><![if !supportLists]><span lang=EN-US
style='font-size:12.0pt;font-family:Wingdings;mso-fareast-font-family:Wingdings;
mso-bidi-font-family:Wingdings;mso-font-kerning:0pt'><span style='mso-list:
Ignore'>l<span style='font:7.0pt "Times New Roman"'>
</span></span></span><![endif]><span lang=EN-US style='font-size:12.0pt;
mso-font-kerning:0pt'>Random hint 2: Remember that when calling <span
class=GramE>read(</span>2) on a socket, the read may return before all data has
been received (i.e., you may get only part of the message). If you are
expecting a certain number of bytes, or a certain “end-of-data” marker, you may
need to do multiple reads to get all the data. (The <span class=GramE>read(</span>2)
call returns the number of bytes read, or 0 on end-of-file.)<o:p></o:p></span></p>
<p class=MsoNormal align=left style='text-align:left;mso-layout-grid-align:
none;text-autospace:none'><span lang=EN-US style='font-size:12.0pt;mso-font-kerning:
0pt'><o:p> </o:p></span></p>
</div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -