1
0
Fork 0
cl-sites/bgnet/common-questions.html
2024-04-02 10:03:42 +02:00

452 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Beej's Guide to Network Programming</title>
<style>
html {
color: #1a1a1a;
background-color: #fdfdfd;
}
body {
margin: 0 auto;
max-width: 36em;
padding-left: 50px;
padding-right: 50px;
padding-top: 50px;
padding-bottom: 50px;
hyphens: auto;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 12px;
}
h1 {
font-size: 1.8em;
}
}
@media print {
html {
background-color: white;
}
body {
background-color: transparent;
color: black;
font-size: 12pt;
}
p, h2, h3 {
orphans: 3;
widows: 3;
}
h2, h3, h4 {
page-break-after: avoid;
}
}
p {
margin: 1em 0;
}
a {
color: #1a1a1a;
}
a:visited {
color: #1a1a1a;
}
img {
max-width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 1.4em;
}
h5, h6 {
font-size: 1em;
font-style: italic;
}
h6 {
font-weight: normal;
}
ol, ul {
padding-left: 1.7em;
margin-top: 1em;
}
li > ol, li > ul {
margin-top: 0;
}
blockquote {
margin: 1em 0 1em 1.7em;
padding-left: 1em;
border-left: 2px solid #e6e6e6;
color: #606060;
}
code {
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
font-size: 85%;
margin: 0;
hyphens: manual;
}
pre {
margin: 1em 0;
overflow: auto;
}
pre code {
padding: 0;
overflow: visible;
overflow-wrap: normal;
}
.sourceCode {
background-color: transparent;
overflow: visible;
}
hr {
background-color: #1a1a1a;
border: none;
height: 1px;
margin: 1em 0;
}
table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
overflow-x: auto;
display: block;
font-variant-numeric: lining-nums tabular-nums;
}
table caption {
margin-bottom: 0.75em;
}
tbody {
margin-top: 0.5em;
border-top: 1px solid #1a1a1a;
border-bottom: 1px solid #1a1a1a;
}
th {
border-top: 1px solid #1a1a1a;
padding: 0.25em 0.5em 0.25em 0.5em;
}
td {
padding: 0.125em 0.5em 0.25em 0.5em;
}
header {
margin-bottom: 4em;
text-align: center;
}
#TOC li {
list-style: none;
}
#TOC ul {
padding-left: 1.3em;
}
#TOC > ul {
padding-left: 0;
}
#TOC a:not(:hover) {
text-decoration: none;
}
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
/* CSS for syntax highlighting */
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { color: #008000; } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { color: #008000; font-weight: bold; } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<link href="https://fonts.googleapis.com/css?family=Roboto|Roboto+Mono&display=swap" rel="stylesheet">
<!-- BG custom styling -->
<style type="text/css">
/* Fix for line numbers not visible */
pre.numberSource code > span {
left: -1em;
}
pre.numberSource {
margin-left: initial;
}
/* Put some space after the section numbers */
span.toc-section-number::after {
content: "\a0\a0\a0"; /* non-breaking whitespace */
}
/* Hide underlines on code number links */
pre > code.sourceCode > span > a:first-child::before {
text-decoration: none;
}
/* Color the source blocks */
div.sourceCode {
background-color: #f0f0f0;
}
/* Fix iOS big text rendering issue */
pre > code.sourceCode > span {
display: initial;
}
/* Color the inline code */
code:not(.sourceCode) {
background: #f0f0f0;
padding-left: 0.2em;
padding-right: 0.2em;
border-radius: 0.2em;
}
/* Keep code tags from wrapping in tables */
tbody code {
white-space: nowrap;
}
td {
vertical-align: top;
}
body {
font-size: 12pt;
max-width: 43em;
}
figure {
text-align: center;
}
</style>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<div style="text-align:center"><span><a href="slightly-advanced-techniques.html">Prev</a> | </span><a href="index.html">Contents</a><span> | <a href="man-pages.html">Next</a></span></div><hr>
<h1 data-number="8" id="common-questions"><span class="header-section-number">8</span> Common Questions</h1>
<p><strong>Where can I get those header files?</strong></p>
<p> If you dont have them on your system already, you probably dont need them. Check the manual for your particular platform. If youre building for Windows, you only need to <code>#include &lt;winsock.h&gt;</code>.</p>
<p><strong>What do I do when <code>bind()</code> reports “Address already in use”?</strong></p>
<p>You have to use <code>setsockopt()</code> with the <code>SO_REUSEADDR</code> option on the listening socket. Check out the <a href="system-calls-or-bust.html#bind">section on <code>bind()</code></a> and the <a href="slightly-advanced-techniques.html#select">section on <code>select()</code></a> for an example.</p>
<p><strong>How do I get a list of open sockets on the system?</strong></p>
<p>Use the <code>netstat</code>. Check the <code>man</code> page for full details, but you should get some good output just typing:</p>
<pre><code>$ netstat</code></pre>
<p>The only trick is determining which socket is associated with which program. <code>:-)</code></p>
<p><strong>How can I view the routing table?</strong></p>
<p>Run the <code>route</code> command (in <code>/sbin</code> on most Linuxes) or the command <code>netstat -r</code>. Or the command <code>ip route</code>.</p>
<p><strong>How can I run the client and server programs if I only have one computer? Dont I need a network to write network programs?</strong></p>
<p>Fortunately for you, virtually all machines implement a loopback network “device” that sits in the kernel and pretends to be a network card. (This is the interface listed as “<code>lo</code>” in the routing table.)</p>
<p>Pretend youre logged into a machine named “<code>goat</code>”. Run the client in one window and the server in another. Or start the server in the background (“<code>server &amp;</code>”) and run the client in the same window. The upshot of the loopback device is that you can either <code>client goat</code> or <code>client localhost</code> (since “<code>localhost</code>” is likely defined in your <code>/etc/hosts</code> file) and youll have the client talking to the server without a network!</p>
<p>In short, no changes are necessary to any of the code to make it run on a single non-networked machine! Huzzah!</p>
<p><strong>How can I tell if the remote side has closed connection?</strong></p>
<p>You can tell because <code>recv()</code> will return <code>0</code>.</p>
<p><strong>How do I implement a “ping” utility? What is ICMP? Where can I find out more about raw sockets and <code>SOCK_RAW</code>?</strong></p>
<p></p>
<p>All your raw sockets questions will be answered in <a href="more-references.html#books">W. Richard Stevens UNIX Network Programming books</a>. Also, look in the <code>ping/</code> subdirectory in Stevens UNIX Network Programming source code, <a href="http://www.unpbook.com/src.html">available online</a><a href="footnotes.html#fn43" class="footnote-ref" id="fnref43" role="doc-noteref"><sup>43</sup></a>.</p>
<p><strong>How do I change or shorten the timeout on a call to <code>connect()</code>?</strong></p>
<p>Instead of giving you exactly the same answer that W. Richard Stevens would give you, Ill just refer you to <a href="http://www.unpbook.com/src.html"><code>lib/connect_nonb.c</code> in the UNIX Network Programming source code</a><a href="footnotes.html#fn44" class="footnote-ref" id="fnref44" role="doc-noteref"><sup>44</sup></a>.</p>
<p>The gist of it is that you make a socket descriptor with <code>socket()</code>, <a href="slightly-advanced-techniques.html#blocking">set it to non-blocking</a>, call <code>connect()</code>, and if all goes well <code>connect()</code> will return <code>-1</code> immediately and <code>errno</code> will be set to <code>EINPROGRESS</code>. Then you call <a href="slightly-advanced-techniques.html#select"><code>select()</code></a> with whatever timeout you want, passing the socket descriptor in both the read and write sets. If it doesnt timeout, it means the <code>connect()</code> call completed. At this point, youll have to use <code>getsockopt()</code> with the <code>SO_ERROR</code> option to get the return value from the <code>connect()</code> call, which should be zero if there was no error.</p>
<p>Finally, youll probably want to set the socket back to be blocking again before you start transferring data over it.</p>
<p>Notice that this has the added benefit of allowing your program to do something else while its connecting, too. You could, for example, set the timeout to something low, like 500 ms, and update an indicator onscreen each timeout, then call <code>select()</code> again. When youve called <code>select()</code> and timed-out, say, 20 times, youll know its time to give up on the connection.</p>
<p>Like I said, check out Stevens source for a perfectly excellent example.</p>
<p><strong>How do I build for Windows?</strong></p>
<p>First, delete Windows and install Linux or BSD. <code>};-)</code>. No, actually, just see the <a href="intro.html#windows">section on building for Windows</a> in the introduction.</p>
<p><strong>How do I build for Solaris/SunOS? I keep getting linker errors when I try to compile!</strong></p>
<p>The linker errors happen because Sun boxes dont automatically compile in the socket libraries. See the <a href="intro.html#solaris">section on building for Solaris/SunOS</a> in the introduction for an example of how to do this.</p>
<p><strong>Why does <code>select()</code> keep falling out on a signal?</strong></p>
<p>Signals tend to cause blocked system calls to return <code>-1</code> with <code>errno</code> set to <code>EINTR</code>. When you set up a signal handler with <code>sigaction()</code>, you can set the flag <code>SA_RESTART</code>, which is supposed to restart the system call after it was interrupted.</p>
<p>Naturally, this doesnt always work.</p>
<p>My favorite solution to this involves a <code>goto</code> statement. You know this irritates your professors to no end, so go for it!</p>
<div class="sourceCode" id="cb78"><pre class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb78-1"><a href="common-questions.html#cb78-1"></a>select_restart<span class="op">:</span></span>
<span id="cb78-2"><a href="common-questions.html#cb78-2"></a><span class="cf">if</span> <span class="op">((</span>err <span class="op">=</span> select<span class="op">(</span>fdmax<span class="op">+</span><span class="dv">1</span><span class="op">,</span> <span class="op">&amp;</span>readfds<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">))</span> <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb78-3"><a href="common-questions.html#cb78-3"></a> <span class="cf">if</span> <span class="op">(</span>errno <span class="op">==</span> EINTR<span class="op">)</span> <span class="op">{</span></span>
<span id="cb78-4"><a href="common-questions.html#cb78-4"></a> <span class="co">// some signal just interrupted us, so restart</span></span>
<span id="cb78-5"><a href="common-questions.html#cb78-5"></a> <span class="cf">goto</span> select_restart<span class="op">;</span></span>
<span id="cb78-6"><a href="common-questions.html#cb78-6"></a> <span class="op">}</span></span>
<span id="cb78-7"><a href="common-questions.html#cb78-7"></a> <span class="co">// handle the real error here:</span></span>
<span id="cb78-8"><a href="common-questions.html#cb78-8"></a> perror<span class="op">(</span><span class="st">&quot;select&quot;</span><span class="op">);</span></span>
<span id="cb78-9"><a href="common-questions.html#cb78-9"></a><span class="op">}</span> </span></code></pre></div>
<p>Sure, you dont <em>need</em> to use <code>goto</code> in this case; you can use other structures to control it. But I think the <code>goto</code> statement is actually cleaner.</p>
<p><strong>How can I implement a timeout on a call to <code>recv()</code>?</strong></p>
<p> Use <a href="slightly-advanced-techniques.html#select"><code>select()</code></a>! It allows you to specify a timeout parameter for socket descriptors that youre looking to read from. Or, you could wrap the entire functionality in a single function, like this:</p>
<div class="sourceCode" id="cb79"><pre class="sourceCode numberSource c numberLines"><code class="sourceCode c"><span id="cb79-1"><a href="common-questions.html#cb79-1"></a><span class="pp">#include </span><span class="im">&lt;unistd.h&gt;</span></span>
<span id="cb79-2"><a href="common-questions.html#cb79-2"></a><span class="pp">#include </span><span class="im">&lt;sys/time.h&gt;</span></span>
<span id="cb79-3"><a href="common-questions.html#cb79-3"></a><span class="pp">#include </span><span class="im">&lt;sys/types.h&gt;</span></span>
<span id="cb79-4"><a href="common-questions.html#cb79-4"></a><span class="pp">#include </span><span class="im">&lt;sys/socket.h&gt;</span></span>
<span id="cb79-5"><a href="common-questions.html#cb79-5"></a></span>
<span id="cb79-6"><a href="common-questions.html#cb79-6"></a><span class="dt">int</span> recvtimeout<span class="op">(</span><span class="dt">int</span> s<span class="op">,</span> <span class="dt">char</span> <span class="op">*</span>buf<span class="op">,</span> <span class="dt">int</span> len<span class="op">,</span> <span class="dt">int</span> timeout<span class="op">)</span></span>
<span id="cb79-7"><a href="common-questions.html#cb79-7"></a><span class="op">{</span></span>
<span id="cb79-8"><a href="common-questions.html#cb79-8"></a> fd_set fds<span class="op">;</span></span>
<span id="cb79-9"><a href="common-questions.html#cb79-9"></a> <span class="dt">int</span> n<span class="op">;</span></span>
<span id="cb79-10"><a href="common-questions.html#cb79-10"></a> <span class="kw">struct</span> timeval tv<span class="op">;</span></span>
<span id="cb79-11"><a href="common-questions.html#cb79-11"></a></span>
<span id="cb79-12"><a href="common-questions.html#cb79-12"></a> <span class="co">// set up the file descriptor set</span></span>
<span id="cb79-13"><a href="common-questions.html#cb79-13"></a> FD_ZERO<span class="op">(&amp;</span>fds<span class="op">);</span></span>
<span id="cb79-14"><a href="common-questions.html#cb79-14"></a> FD_SET<span class="op">(</span>s<span class="op">,</span> <span class="op">&amp;</span>fds<span class="op">);</span></span>
<span id="cb79-15"><a href="common-questions.html#cb79-15"></a></span>
<span id="cb79-16"><a href="common-questions.html#cb79-16"></a> <span class="co">// set up the struct timeval for the timeout</span></span>
<span id="cb79-17"><a href="common-questions.html#cb79-17"></a> tv<span class="op">.</span>tv_sec <span class="op">=</span> timeout<span class="op">;</span></span>
<span id="cb79-18"><a href="common-questions.html#cb79-18"></a> tv<span class="op">.</span>tv_usec <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb79-19"><a href="common-questions.html#cb79-19"></a></span>
<span id="cb79-20"><a href="common-questions.html#cb79-20"></a> <span class="co">// wait until timeout or data received</span></span>
<span id="cb79-21"><a href="common-questions.html#cb79-21"></a> n <span class="op">=</span> select<span class="op">(</span>s<span class="op">+</span><span class="dv">1</span><span class="op">,</span> <span class="op">&amp;</span>fds<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">,</span> <span class="op">&amp;</span>tv<span class="op">);</span></span>
<span id="cb79-22"><a href="common-questions.html#cb79-22"></a> <span class="cf">if</span> <span class="op">(</span>n <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="cf">return</span> <span class="op">-</span><span class="dv">2</span><span class="op">;</span> <span class="co">// timeout!</span></span>
<span id="cb79-23"><a href="common-questions.html#cb79-23"></a> <span class="cf">if</span> <span class="op">(</span>n <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span> <span class="cf">return</span> <span class="op">-</span><span class="dv">1</span><span class="op">;</span> <span class="co">// error</span></span>
<span id="cb79-24"><a href="common-questions.html#cb79-24"></a></span>
<span id="cb79-25"><a href="common-questions.html#cb79-25"></a> <span class="co">// data must be here, so do a normal recv()</span></span>
<span id="cb79-26"><a href="common-questions.html#cb79-26"></a> <span class="cf">return</span> recv<span class="op">(</span>s<span class="op">,</span> buf<span class="op">,</span> len<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb79-27"><a href="common-questions.html#cb79-27"></a><span class="op">}</span></span>
<span id="cb79-28"><a href="common-questions.html#cb79-28"></a><span class="op">.</span></span>
<span id="cb79-29"><a href="common-questions.html#cb79-29"></a><span class="op">.</span></span>
<span id="cb79-30"><a href="common-questions.html#cb79-30"></a><span class="op">.</span></span>
<span id="cb79-31"><a href="common-questions.html#cb79-31"></a><span class="co">// Sample call to recvtimeout():</span></span>
<span id="cb79-32"><a href="common-questions.html#cb79-32"></a>n <span class="op">=</span> recvtimeout<span class="op">(</span>s<span class="op">,</span> buf<span class="op">,</span> <span class="kw">sizeof</span> buf<span class="op">,</span> <span class="dv">10</span><span class="op">);</span> <span class="co">// 10 second timeout</span></span>
<span id="cb79-33"><a href="common-questions.html#cb79-33"></a></span>
<span id="cb79-34"><a href="common-questions.html#cb79-34"></a><span class="cf">if</span> <span class="op">(</span>n <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb79-35"><a href="common-questions.html#cb79-35"></a> <span class="co">// error occurred</span></span>
<span id="cb79-36"><a href="common-questions.html#cb79-36"></a> perror<span class="op">(</span><span class="st">&quot;recvtimeout&quot;</span><span class="op">);</span></span>
<span id="cb79-37"><a href="common-questions.html#cb79-37"></a><span class="op">}</span></span>
<span id="cb79-38"><a href="common-questions.html#cb79-38"></a><span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>n <span class="op">==</span> <span class="op">-</span><span class="dv">2</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb79-39"><a href="common-questions.html#cb79-39"></a> <span class="co">// timeout occurred</span></span>
<span id="cb79-40"><a href="common-questions.html#cb79-40"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb79-41"><a href="common-questions.html#cb79-41"></a> <span class="co">// got some data in buf</span></span>
<span id="cb79-42"><a href="common-questions.html#cb79-42"></a><span class="op">}</span></span>
<span id="cb79-43"><a href="common-questions.html#cb79-43"></a><span class="op">.</span></span>
<span id="cb79-44"><a href="common-questions.html#cb79-44"></a><span class="op">.</span></span>
<span id="cb79-45"><a href="common-questions.html#cb79-45"></a><span class="op">.</span> </span></code></pre></div>
<p>Notice that <code>recvtimeout()</code> returns <code>-2</code> in case of a timeout. Why not return <code>0</code>? Well, if you recall, a return value of <code>0</code> on a call to <code>recv()</code> means that the remote side closed the connection. So that return value is already spoken for, and <code>-1</code> means “error”, so I chose <code>-2</code> as my timeout indicator.</p>
<p><strong>How do I encrypt or compress the data before sending it through the socket?</strong></p>
<p>One easy way to do encryption is to use SSL (secure sockets layer), but thats beyond the scope of this guide. (Check out the <a href="https://www.openssl.org/">OpenSSL project</a><a href="footnotes.html#fn45" class="footnote-ref" id="fnref45" role="doc-noteref"><sup>45</sup></a> for more info.)</p>
<p>But assuming you want to plug in or implement your own compressor or encryption system, its just a matter of thinking of your data as running through a sequence of steps between both ends. Each step changes the data in some way.</p>
<ol type="1">
<li>server reads data from file (or wherever)</li>
<li>server encrypts/compresses data (you add this part)</li>
<li>server <code>send()</code>s encrypted data</li>
</ol>
<p>Now the other way around:</p>
<ol type="1">
<li>client <code>recv()</code>s encrypted data</li>
<li>client decrypts/decompresses data (you add this part)</li>
<li>client writes data to file (or wherever)</li>
</ol>
<p>If youre going to compress and encrypt, just remember to compress first. <code>:-)</code></p>
<p>Just as long as the client properly undoes what the server does, the data will be fine in the end no matter how many intermediate steps you add.</p>
<p>So all you need to do to use my code is to find the place between where the data is read and the data is sent (using <code>send()</code>) over the network, and stick some code in there that does the encryption.</p>
<p><strong>What is this “<code>PF_INET</code>” I keep seeing? Is it related to <code>AF_INET</code>?</strong></p>
<p> </p>
<p>Yes, yes it is. See <a href="system-calls-or-bust.html#socket">the section on <code>socket()</code></a> for details.</p>
<p><strong>How can I write a server that accepts shell commands from a client and executes them?</strong></p>
<p>For simplicity, lets say the client <code>connect()</code>s, <code>send()</code>s, and <code>close()</code>s the connection (that is, there are no subsequent system calls without the client connecting again).</p>
<p>The process the client follows is this:</p>
<ol type="1">
<li><code>connect()</code> to server</li>
<li><code>send("/sbin/ls &gt; /tmp/client.out")</code></li>
<li><code>close()</code> the connection</li>
</ol>
<p>Meanwhile, the server is handling the data and executing it:</p>
<ol type="1">
<li><code>accept()</code> the connection from the client</li>
<li><code>recv(str)</code> the command string</li>
<li><code>close()</code> the connection</li>
<li><code>system(str)</code> to run the command</li>
</ol>
<p> <em>Beware!</em> Having the server execute what the client says is like giving remote shell access and people can do things to your account when they connect to the server. For instance, in the above example, what if the client sends “<code>rm -rf ~</code>”? It deletes everything in your account, thats what!</p>
<p>So you get wise, and you prevent the client from using any except for a couple utilities that you know are safe, like the <code>foobar</code> utility:</p>
<div class="sourceCode" id="cb80"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb80-1"><a href="common-questions.html#cb80-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(!</span>strncmp<span class="op">(</span>str<span class="op">,</span> <span class="st">&quot;foobar&quot;</span><span class="op">,</span> <span class="dv">6</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb80-2"><a href="common-questions.html#cb80-2" aria-hidden="true" tabindex="-1"></a> sprintf<span class="op">(</span>sysstr<span class="op">,</span> <span class="st">&quot;</span><span class="sc">%s</span><span class="st"> &gt; /tmp/server.out&quot;</span><span class="op">,</span> str<span class="op">);</span></span>
<span id="cb80-3"><a href="common-questions.html#cb80-3" aria-hidden="true" tabindex="-1"></a> system<span class="op">(</span>sysstr<span class="op">);</span></span>
<span id="cb80-4"><a href="common-questions.html#cb80-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> </span></code></pre></div>
<p>But youre still unsafe, unfortunately: what if the client enters “<code>foobar; rm -rf ~</code>”? The safest thing to do is to write a little routine that puts an escape (“<code>\</code>”) character in front of all non-alphanumeric characters (including spaces, if appropriate) in the arguments for the command.</p>
<p>As you can see, security is a pretty big issue when the server starts executing things the client sends.</p>
<p><strong>Im sending a slew of data, but when I <code>recv()</code>, it only receives 536 bytes or 1460 bytes at a time. But if I run it on my local machine, it receives all the data at the same time. Whats going on?</strong></p>
<p>Youre hitting the MTU—the maximum size the physical medium can handle. On the local machine, youre using the loopback device which can handle 8K or more no problem. But on Ethernet, which can only handle 1500 bytes with a header, you hit that limit. Over a modem, with 576 MTU (again, with header), you hit the even lower limit.</p>
<p>You have to make sure all the data is being sent, first of all. (See the <a href="slightly-advanced-techniques.html#sendall"><code>sendall()</code></a> function implementation for details.) Once youre sure of that, then you need to call <code>recv()</code> in a loop until all your data is read.</p>
<p>Read the section <a href="slightly-advanced-techniques.html#sonofdataencap">Son of Data Encapsulation</a> for details on receiving complete packets of data using multiple calls to <code>recv()</code>.</p>
<p><strong>Im on a Windows box and I dont have the <code>fork()</code> system call or any kind of <code>struct sigaction</code>. What to do?</strong></p>
<p> If theyre anywhere, theyll be in POSIX libraries that may have shipped with your compiler. Since I dont have a Windows box, I really cant tell you the answer, but I seem to remember that Microsoft has a POSIX compatibility layer and thats where <code>fork()</code> would be. (And maybe even <code>sigaction</code>.)</p>
<p>Search the help that came with VC++ for “fork” or “POSIX” and see if it gives you any clues.</p>
<p>If that doesnt work at all, ditch the <code>fork()</code>/<code>sigaction</code> stuff and replace it with the Win32 equivalent: <code>CreateProcess()</code>. I dont know how to use <code>CreateProcess()</code>—it takes a bazillion arguments, but it should be covered in the docs that came with VC++.</p>
<p><strong> Im behind a firewall—how do I let people outside the firewall know my IP address so they can connect to my machine?</strong></p>
<p>Unfortunately, the purpose of a firewall is to prevent people outside the firewall from connecting to machines inside the firewall, so allowing them to do so is basically considered a breach of security.</p>
<p>This isnt to say that all is lost. For one thing, you can still often <code>connect()</code> through the firewall if its doing some kind of masquerading or NAT or something like that. Just design your programs so that youre always the one initiating the connection, and youll be fine.</p>
<p> If thats not satisfactory, you can ask your sysadmins to poke a hole in the firewall so that people can connect to you. The firewall can forward to you either through its NAT software, or through a proxy or something like that.</p>
<p>Be aware that a hole in the firewall is nothing to be taken lightly. You have to make sure you dont give bad people access to the internal network; if youre a beginner, its a lot harder to make software secure than you might imagine.</p>
<p>Dont make your sysadmin mad at me. <code>;-)</code></p>
<p><strong> How do I write a packet sniffer? How do I put my Ethernet interface into promiscuous mode?</strong></p>
<p>For those not in the know, when a network card is in “promiscuous mode”, it will forward ALL packets to the operating system, not just those that were addressed to this particular machine. (Were talking Ethernet-layer addresses here, not IP addressesbut since ethernet is lower-layer than IP, all IP addresses are effectively forwarded as well. See the section <a href="what-is-a-socket.html#lowlevel">Low Level Nonsense and Network Theory</a> for more info.)</p>
<p>This is the basis for how a packet sniffer works. It puts the interface into promiscuous mode, then the OS gets every single packet that goes by on the wire. Youll have a socket of some type that you can read this data from.</p>
<p>Unfortunately, the answer to the question varies depending on the platform, but if you Google for, for instance, “windows promiscuous ioctl” youll probably get somewhere. For Linux, theres what looks like a <a href="https://stackoverflow.com/questions/21323023/">useful Stack Overflow thread</a><a href="footnotes.html#fn46" class="footnote-ref" id="fnref46" role="doc-noteref"><sup>46</sup></a>, as well.</p>
<p><strong>How can I set a custom timeout value for a TCP or UDP socket?</strong></p>
<p>It depends on your system. You might search the net for <code>SO_RCVTIMEO</code> and <code>SO_SNDTIMEO</code> (for use with <code>setsockopt()</code>) to see if your system supports such functionality.</p>
<p>The Linux man page suggests using <code>alarm()</code> or <code>setitimer()</code> as a substitute.</p>
<p><strong>How can I tell which ports are available to use? Is there a list of “official” port numbers?</strong></p>
<p>Usually this isnt an issue. If youre writing, say, a web server, then its a good idea to use the well-known port 80 for your software. If youre writing just your own specialized server, then choose a port at random (but greater than 1023) and give it a try.</p>
<p>If the port is already in use, youll get an “Address already in use” error when you try to <code>bind()</code>. Choose another port. (Its a good idea to allow the user of your software to specify an alternate port either with a config file or a command line switch.)</p>
<p>There is a <a href="https://www.iana.org/assignments/port-numbers">list of official port numbers</a><a href="footnotes.html#fn47" class="footnote-ref" id="fnref47" role="doc-noteref"><sup>47</sup></a> maintained by the Internet Assigned Numbers Authority (IANA). Just because something (over 1023) is in that list doesnt mean you cant use the port. For instance, Id Softwares DOOM uses the same port as “mdqs”, whatever that is. All that matters is that no one else <em>on the same machine</em> is using that port when you want to use it.</p>
<hr><div style="text-align:center"><span><a href="slightly-advanced-techniques.html">Prev</a> | </span><a href="index.html">Contents</a><span> | <a href="man-pages.html">Next</a></span></div></body>
</html>