ibm-information-center/dist/eclipse/plugins/i5OS.ic.rzab6_5.4.0.1/poll.htm

446 lines
19 KiB
HTML

<?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 lang="en-us" xml:lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="security" content="public" />
<meta name="Robots" content="index,follow" />
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
<meta name="DC.Type" content="reference" />
<meta name="DC.Title" content="Use poll() instead of select()" />
<meta name="abstract" content="The poll() API is part of the Single Unix Specification and the UNIX 95/98 standard. The poll() API performs the same function as the existing select() API. The only difference between these two APIs is the interface that is provided to the caller." />
<meta name="description" content="The poll() API is part of the Single Unix Specification and the UNIX 95/98 standard. The poll() API performs the same function as the existing select() API. The only difference between these two APIs is the interface that is provided to the caller." />
<meta name="DC.Relation" scheme="URI" content="example.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/accept.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/recv.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/ioctl.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/send.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/listen.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/close.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/socket.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/bind.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/ssocko.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/poll.htm" />
<meta name="copyright" content="(C) Copyright IBM Corporation 2001, 2006" />
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 2001, 2006" />
<meta name="DC.Format" content="XHTML" />
<meta name="DC.Identifier" content="poll" />
<meta name="DC.Language" content="en-us" />
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
<link rel="stylesheet" type="text/css" href="./ic.css" />
<title>Use poll() instead of select()</title>
</head>
<body id="poll"><a name="poll"><!-- --></a>
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
<h1 class="topictitle1">Use <span class="apiname">poll()</span> instead of <span class="apiname">select()</span></h1>
<div><p>The <span class="apiname">poll()</span> API is part of the Single Unix Specification
and the UNIX<sup>®</sup> 95/98
standard. The <span class="apiname">poll()</span> API performs the same function as
the existing <span class="apiname">select()</span> API. The only difference between
these two APIs is the interface that is provided to the caller.</p>
<div class="section"><p>The <span class="apiname">select()</span> API requires that
the application pass in an array of bits in which one bit is used to represent
each descriptor number. When descriptor numbers are very large, it can overflow
the 30KB allocated memory size, forcing multiple iterations of
the process. This overhead can adversely affect performance.</p>
</div>
<div class="section"><p>The <span class="apiname">poll()</span> API allows the application
to pass an array of structures rather than an array of bits. Because each
pollfd structure can contain up to 8 bytes, the application only needs to
pass one structure for each descriptor, even if descriptor numbers are very
large.</p>
</div>
<div class="section"><p></p>
</div>
<div class="section"><h4 class="sectiontitle">Socket flow of events: Server that uses <span class="apiname">poll()</span></h4><p>The
following calls are used in the example:</p>
<ol><li>The <span class="apiname">socket()</span> function returns a socket descriptor representing
an endpoint. The statement also identifies that the AF_INET (Internet Protocol)
address family with the TCP transport (SOCK_STREAM) being used for this socket.</li>
<li>The <span class="apiname">setsockopt</span> function allows application to reuse
the local address when the server is restarted before the required wait time
expires. </li>
<li>The <span class="apiname">ioctl()</span> function sets the socket
to be nonblocking. All of the sockets for the incoming connections are also
nonblocking because they inherit that state from the listening socket.</li>
<li>After the socket descriptor is created, the <span class="apiname">bind()</span> function
gets a unique name for the socket. </li>
<li>The <span class="apiname">listen()</span> function call allows the server to accept
incoming client connections. </li>
<li>The <span class="apiname">poll()</span> function allows the process to wait for
an event to occur and to wake up the process when the event occurs. Poll might
return one of the following values. <dl><dt class="dlterm">0</dt>
<dd>Indicates that the process times out. In this example, the timeout is
set for 3 minutes (in milliseconds).</dd>
<dt class="dlterm">-1</dt>
<dd>Indicates that the process has failed.</dd>
<dt class="dlterm">1</dt>
<dd>Indicates only one descriptor is ready to be processed, which is processed
only if it is the listening socket</dd>
<dt class="dlterm">1++</dt>
<dd>Indicates multiple descriptors waiting to be processed. The poll() API
allows simultaneous connection with all descriptors in the queue on the listening
socket.</dd>
</dl>
</li>
<li>The <span class="apiname">accept()</span> and <span class="apiname">recv()</span> functions
are completed when the EWOULDBLOCK is returned. </li>
<li>The <span class="apiname">send()</span> function echoes the data back to the client. </li>
<li>The <span class="apiname">close()</span> function closes any open socket descriptors.</li>
</ol>
</div>
<div class="section"><div class="note"><span class="notetitle">Note:</span> By using the code examples, you agree to the terms of the <a href="codedisclaimer.htm">Code license and disclaimer information</a>.</div>
<pre>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/ioctl.h&gt;
#include &lt;sys/poll.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;sys/time.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;errno.h&gt;
#define SERVER_PORT 12345
#define TRUE 1
#define FALSE 0
main (int argc, char *argv[])
{
int len, rc, on = 1;
int listen_sd = -1, new_sd = -1;
int desc_ready, end_server = FALSE, compress_array = FALSE;
int close_conn;
char buffer[80];
struct sockaddr_in addr;
int timeout;
struct pollfd fds[200];
int nfds = 1, current_size = 0, i, j;
/*************************************************************/
/* Create an AF_INET stream socket to receive incoming */
/* connections on */
/*************************************************************/
listen_sd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sd &lt; 0)
{
perror("socket() failed");
exit(-1);
}
/*************************************************************/
/* Allow socket descriptor to be reuseable */
/*************************************************************/
rc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR,
(char *)&amp;on, sizeof(on));
if (rc &lt; 0)
{
perror("setsockopt() failed");
close(listen_sd);
exit(-1);
}
/*************************************************************/
/* Set socket to be nonblocking. All of the sockets for */
/* the incoming connections will also be nonblocking since */
/* they will inherit that state from the listening socket. */
/*************************************************************/
rc = ioctl(listen_sd, FIONBIO, (char *)&amp;on);
if (rc &lt; 0)
{
perror("ioctl() failed");
close(listen_sd);
exit(-1);
}
/*************************************************************/
/* Bind the socket */
/*************************************************************/
memset(&amp;addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERVER_PORT);
rc = bind(listen_sd,
(struct sockaddr *)&amp;addr, sizeof(addr));
if (rc &lt; 0)
{
perror("bind() failed");
close(listen_sd);
exit(-1);
}
/*************************************************************/
/* Set the listen back log */
/*************************************************************/
rc = listen(listen_sd, 32);
if (rc &lt; 0)
{
perror("listen() failed");
close(listen_sd);
exit(-1);
}
/*************************************************************/
/* Initialize the pollfd structure */
/*************************************************************/
memset(fds, 0 , sizeof(fds));
/*************************************************************/
/* Setup the initial listening socket */
/*************************************************************/
fds[0].fd = listen_sd;
fds[0].events = POLLIN;
/*************************************************************/
/* Initialize the timeout to 3 minutes. If no */
/* activity after 3 minutes this program will end. */
/* timeout value is based on milliseconds. */
/*************************************************************/
timeout = (3 * 60 * 1000);
/*************************************************************/
/* Loop waiting for incoming connects or for incoming data */
/* on any of the connected sockets. */
/*************************************************************/
do
{
/***********************************************************/
/* Call poll() and wait 3 minutes for it to complete. */
/***********************************************************/
printf("Waiting on poll()...\n");
rc = poll(fds, nfds, timeout);
/***********************************************************/
/* Check to see if the poll call failed. */
/***********************************************************/
if (rc &lt; 0)
{
perror(" poll() failed");
break;
}
/***********************************************************/
/* Check to see if the 3 minute time out expired. */
/***********************************************************/
if (rc == 0)
{
printf(" poll() timed out. End program.\n");
break;
}
/***********************************************************/
/* One or more descriptors are readable. Need to */
/* determine which ones they are. */
/***********************************************************/
current_size = nfds;
for (i = 0; i &lt; current_size; i++)
{
/*********************************************************/
/* Loop through to find the descriptors that returned */
/* POLLIN and determine whether it's the listening */
/* or the active connection. */
/*********************************************************/
if(fds[i].revents == 0)
continue;
/*********************************************************/
/* If revents is not POLLIN, it's an unexpected result, */
/* log and end the server. */
/*********************************************************/
if(fds[i].revents != POLLIN)
{
printf(" Error! revents = %d\n", fds[i].revents);
end_server = TRUE;
break;
}
if (fds[i].fd == listen_sd)
{
/*******************************************************/
/* Listening descriptor is readable. */
/*******************************************************/
printf(" Listening socket is readable\n");
/*******************************************************/
/* Accept all incoming connections that are */
/* queued up on the listening socket before we */
/* loop back and call poll again. */
/*******************************************************/
do
{
/*****************************************************/
/* Accept each incoming connection. If */
/* accept fails with EWOULDBLOCK, then we */
/* have accepted all of them. Any other */
/* failure on accept will cause us to end the */
/* server. */
/*****************************************************/
new_sd = accept(listen_sd, NULL, NULL);
if (new_sd &lt; 0)
{
if (errno != EWOULDBLOCK)
{
perror(" accept() failed");
end_server = TRUE;
}
break;
}
/*****************************************************/
/* Add the new incoming connection to the */
/* pollfd structure */
/*****************************************************/
printf(" New incoming connection - %d\n", new_sd);
fds[nfds].fd = new_sd;
fds[nfds].events = POLLIN;
nfds++;
/*****************************************************/
/* Loop back up and accept another incoming */
/* connection */
/*****************************************************/
} while (new_sd != -1);
}
/*********************************************************/
/* This is not the listening socket, therefore an */
/* existing connection must be readable */
/*********************************************************/
else
{
printf(" Descriptor %d is readable\n", fds[i].fd);
close_conn = FALSE;
/*******************************************************/
/* Receive all incoming data on this socket */
/* before we loop back and call poll again. */
/*******************************************************/
do
{
/*****************************************************/
/* Receive data on this connection until the */
/* recv fails with EWOULDBLOCK. If any other */
/* failure occurs, we will close the */
/* connection. */
/*****************************************************/
rc = recv(fds[i].fd, buffer, sizeof(buffer), 0);
if (rc &lt; 0)
{
if (errno != EWOULDBLOCK)
{
perror(" recv() failed");
close_conn = TRUE;
}
break;
}
/*****************************************************/
/* Check to see if the connection has been */
/* closed by the client */
/*****************************************************/
if (rc == 0)
{
printf(" Connection closed\n");
close_conn = TRUE;
break;
}
/*****************************************************/
/* Data was received */
/*****************************************************/
len = rc;
printf(" %d bytes received\n", len);
/*****************************************************/
/* Echo the data back to the client */
/*****************************************************/
rc = send(fds[i].fd, buffer, len, 0);
if (rc &lt; 0)
{
perror(" send() failed");
close_conn = TRUE;
break;
}
} while(TRUE);
/*******************************************************/
/* If the close_conn flag was turned on, we need */
/* to clean up this active connection. This */
/* clean up process includes removing the */
/* descriptor. */
/*******************************************************/
if (close_conn)
{
close(fds[i].fd);
fds[i].fd = -1;
compress_array = TRUE;
}
} /* End of existing connection is readable */
} /* End of loop through pollable descriptors */
/***********************************************************/
/* If the compress_array flag was turned on, we need */
/* to squeeze together the array and decrement the number */
/* of file descriptors. We do not need to move back the */
/* events and revents fields because the events will always*/
/* be POLLIN in this case, and revents is output. */
/***********************************************************/
if (compress_array)
{
compress_array = FALSE;
for (i = 0; i &lt; nfds; i++)
{
if (fds[i].fd == -1)
{
for(j = i; j &lt; nfds; j++)
{
fds[j].fd = fds[j+1].fd;
}
nfds--;
}
}
}
} while (end_server == FALSE); /* End of serving running. */
/*************************************************************/
/* Clean up all of the sockets that are open */
/*************************************************************/
for (i = 0; i &lt; nfds; i++)
{
if(fds[i].fd &gt;= 0)
close(fds[i].fd);
}
}
</pre>
</div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="example.htm" title="These examples provide many sample programs that illustrate the more advanced socket concepts. You can use these sample programs to create your own applications that complete a similar task.">Examples: Socket application designs</a></div>
</div>
<div class="relinfo"><strong>Related information</strong><br />
<div><a href="../apis/accept.htm">accept()</a></div>
<div><a href="../apis/recv.htm">recv()</a></div>
<div><a href="../apis/ioctl.htm">ioctl()</a></div>
<div><a href="../apis/send.htm">send()</a></div>
<div><a href="../apis/listen.htm">listen()</a></div>
<div><a href="../apis/close.htm">close()</a></div>
<div><a href="../apis/socket.htm">socket()</a></div>
<div><a href="../apis/bind.htm">bind()</a></div>
<div><a href="../apis/ssocko.htm">setsockopt</a></div>
<div><a href="../apis/poll.htm">poll()</a></div>
</div>
</div>
</body>
</html>