The translation is temporarily closed for contributions due to maintenance, please come back later.

Source string Read only

(itstool) path: sect4/para
Context English State
There are 65535 <acronym>IP</acronym> ports, but a server usually processes requests that come in on only one of them. It is like telling the phone room operator that we are now at work and available to answer the phone at a specific extension. We use <citerefentry><refentrytitle>bind</refentrytitle><manvolnum>2</manvolnum></citerefentry> to tell sockets which port we want to serve.
int bind(int s, const struct sockaddr *addr, socklen_t addrlen);
Beside specifying the port in <varname>addr</varname>, the server may include its <acronym>IP</acronym> address. However, it can just use the symbolic constant <symbol>INADDR_ANY</symbol> to indicate it will serve all requests to the specified port regardless of what its <acronym>IP</acronym> address is. This symbol, along with several similar ones, is declared in <filename>netinet/in.h</filename>
#define INADDR_ANY (u_int32_t)0x00000000
Suppose we were writing a server for the <emphasis>daytime</emphasis> protocol over <acronym>TCP</acronym>/<acronym>IP</acronym>. Recall that it uses port 13. Our <varname>sockaddr_in</varname> structure would look like this:
_ external ref='sockets/sainserv' md5='__failed__'
0 1 2 3
+--------+--------+--------+--------+
0 | 0 | 2 | 0 | 13 |
+--------+--------+--------+--------+
4 | 0 |
+-----------------------------------+
8 | 0 |
+-----------------------------------+
12 | 0 |
+-----------------------------------+
<imageobject> <imagedata fileref="sockets/sainserv"/> </imageobject> <textobject> <_:literallayout-1/> </textobject> <textobject> <phrase>Example Server sockaddr_in</phrase> </textobject>
<function>listen</function>
To continue our office phone analogy, after you have told the phone central operator what extension you will be at, you now walk into your office, and make sure your own phone is plugged in and the ringer is turned on. Plus, you make sure your call waiting is activated, so you can hear the phone ring even while you are talking to someone.
The server ensures all of that with the <citerefentry><refentrytitle>listen</refentrytitle><manvolnum>2</manvolnum></citerefentry> function.
int listen(int s, int backlog);
In here, the <varname>backlog</varname> variable tells sockets how many incoming requests to accept while you are busy processing the last request. In other words, it determines the maximum size of the queue of pending connections.
<function>accept</function>
After you hear the phone ringing, you accept the call by answering the call. You have now established a connection with your client. This connection remains active until either you or your client hang up.
The server accepts the connection by using the <citerefentry><refentrytitle>accept</refentrytitle><manvolnum>2</manvolnum></citerefentry> function.
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
Note that this time <varname>addrlen</varname> is a pointer. This is necessary because in this case it is the socket that fills out <varname>addr</varname>, the <varname>sockaddr_in</varname> structure.
The return value is an integer. Indeed, the <function>accept</function> returns a <emphasis>new socket</emphasis>. You will use this new socket to communicate with the client.
What happens to the old socket? It continues to listen for more requests (remember the <varname>backlog</varname> variable we passed to <function>listen</function>?) until we <function>close</function> it.
Now, the new socket is meant only for communications. It is fully connected. We cannot pass it to <function>listen</function> again, trying to accept additional connections.
Our First Server
Our first server will be somewhat more complex than our first client was: Not only do we have more sockets functions to use, but we need to write it as a daemon.
This is best achieved by creating a <emphasis>child process</emphasis> after binding the port. The main process then exits and returns control to the <application>shell</application> (or whatever program invoked it).
The child calls <function>listen</function>, then starts an endless loop, which accepts a connection, serves it, and eventually closes its socket.
/*
* daytimed - a port 13 server
*
* Programmed by G. Adam Stanislav
* June 19, 2001
*/
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;time.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;netinet/in.h&gt;

#define BACKLOG 4

int main() {
register int s, c;
int b;
struct sockaddr_in sa;
time_t t;
struct tm *tm;
FILE *client;

if ((s = socket(PF_INET, SOCK_STREAM, 0)) &lt; 0) {
perror("socket");
return 1;
}

bzero(&amp;sa, sizeof sa);

sa.sin_family = AF_INET;
sa.sin_port = htons(13);

if (INADDR_ANY)
sa.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(s, (struct sockaddr *)&amp;sa, sizeof sa) &lt; 0) {
perror("bind");
return 2;
}

switch (fork()) {
case -1:
perror("fork");
return 3;
break;
default:
close(s);
return 0;
break;
case 0:
break;
}

listen(s, BACKLOG);

for (;;) {
b = sizeof sa;

if ((c = accept(s, (struct sockaddr *)&amp;sa, &amp;b)) &lt; 0) {
perror("daytimed accept");
return 4;
}

if ((client = fdopen(c, "w")) == NULL) {
perror("daytimed fdopen");
return 5;
}

if ((t = time(NULL)) &lt; 0) {
perror("daytimed time");

return 6;
}

tm = gmtime(&amp;t);
fprintf(client, "%.4i-%.2i-%.2iT%.2i:%.2i:%.2iZ\n",
tm-&gt;tm_year + 1900,
tm-&gt;tm_mon + 1,
tm-&gt;tm_mday,
tm-&gt;tm_hour,
tm-&gt;tm_min,
tm-&gt;tm_sec);

fclose(client);
}
}
We start by creating a socket. Then we fill out the <varname>sockaddr_in</varname> structure in <varname>sa</varname>. Note the conditional use of <symbol>INADDR_ANY</symbol>:
if (INADDR_ANY)
sa.sin_addr.s_addr = htonl(INADDR_ANY);
Its value is <constant>0</constant>. Since we have just used <function>bzero</function> on the entire structure, it would be redundant to set it to <constant>0</constant> again. But if we port our code to some other system where <symbol>INADDR_ANY</symbol> is perhaps not a zero, we need to assign it to <varname>sa.sin_addr.s_addr</varname>. Most modern C compilers are clever enough to notice that <symbol>INADDR_ANY</symbol> is a constant. As long as it is a zero, they will optimize the entire conditional statement out of the code.
After we have called <function>bind</function> successfully, we are ready to become a <emphasis>daemon</emphasis>: We use <function>fork</function> to create a child process. In both, the parent and the child, the <varname>s</varname> variable is our socket. The parent process will not need it, so it calls <function>close</function>, then it returns <constant>0</constant> to inform its own parent it had terminated successfully.
Meanwhile, the child process continues working in the background. It calls <function>listen</function> and sets its backlog to <constant>4</constant>. It does not need a large value here because <emphasis>daytime</emphasis> is not a protocol many clients request all the time, and because it can process each request instantly anyway.

Loading…

No matching activity found.

Browse all component changes

Source information

Source string comment
(itstool) path: sect4/para
Flags
read-only
Source string location
book.translate.xml:6001
String age
a year ago
Source string age
a year ago
Translation file
books/developers-handbook.pot, string 993