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

337 lines
19 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.

<?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="Example: Accept connections from both IPv6 and IPv4 clients" />
<meta name="abstract" content="Use this sample program to create a server/client model that accepts requests from both IPv4 (those socket applications that use the AF_INET address family) and IPv6 (those applications that use the AF_INET6 address family)." />
<meta name="description" content="Use this sample program to create a server/client model that accepts requests from both IPv4 (those socket applications that use the AF_INET address family) and IPv6 (those applications that use the AF_INET6 address family)." />
<meta name="DC.Relation" scheme="URI" content="ip6scen.htm" />
<meta name="DC.Relation" scheme="URI" content="xcodesigns.htm" />
<meta name="DC.Relation" scheme="URI" content="xip6client.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/socket.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/ssocko.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/bind.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/listen.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/accept.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/gpeern.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/recv.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/send.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/close.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/inet_pton.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/getaddrinfo.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/connec.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="xacceptboth" />
<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>Example: Accept connections from both IPv6 and IPv4 clients</title>
</head>
<body id="xacceptboth"><a name="xacceptboth"><!-- --></a>
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
<h1 class="topictitle1">Example: Accept connections from both IPv6 and IPv4 clients</h1>
<div><p>Use this sample program to create a server/client model that accepts
requests from both IPv4 (those socket applications that use the AF_INET address
family) and IPv6 (those applications that use the AF_INET6 address family).</p>
<div class="section"><p>Currently your socket application can only use
the AF_INET address family, which allows for TCP and User Datagram Protocol
(UDP) protocol; however, this might change with the increase in the use of
IPv6 addresses. You can use this sample program to create your own applications
that accommodate both address families. </p>
</div>
<div class="section"><p>This figure shows how this example program works:</p>
</div>
<div class="section"><p><br /><img src="rzab6511.gif" alt="Socket flow of events: Server application that accepts requests from both IPv4 and IPv6" /><br /></p>
</div>
<div class="section"><h4 class="sectiontitle">Socket flow of events: Server application that accepts requests
from both IPv4 and IPv6 clients</h4><p>This flow describes each of the
function calls and what they do within the socket application that accepts
requests both IPv4 and IPv6 clients.</p>
<ol><li>The <span class="apiname">socket()</span> API specifies a socket descriptor that
creates an endpoint. It also specifies the AF_INET6 address family, which
supports IPv6, and the TCP transport (SOCK_STREAM) is 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>A <span class="apiname">bind()</span> function supplies a unique
name for the socket. In this example, the programmer sets the address to in6addr_any,
which (by default) allows connections to be established from any IPv4 or IPv6
client that specifies port 3005 (that is, the bind is done to both the IPv4
and IPv6 port spaces). <div class="note"><span class="notetitle">Note:</span> If the server only needs to handle IPv6 clients,
then IPv6_ONLY socket option can be used. </div>
</li>
<li>The <span class="apiname">listen()</span> function allows the server to accept incoming
client connections. In this example, the programmer sets the backlog to 10,
which allows the system to queue 10 connection requests before the system
starts rejecting incoming requests.</li>
<li>The server uses the <span class="apiname">accept()</span> function to accept an
incoming connection request. The <span class="apiname">accept()</span> call blocks
indefinitely waiting for the incoming connection to arrive from an IPv4 or
IPv6 client. </li>
<li>The <span class="apiname">getpeername()</span> function returns the client's address
to the application. If the client is an IPv4 client, the address is shown
as an IPv4mapped IPv6 address.</li>
<li>The <span class="apiname">recv()</span> function receives that 250
bytes of data from the client. In this example, the client sends 250 bytes
of data over. Knowing this, the programmer uses the SO_RCVLOWAT socket option
and specify that he or she does not want the <span class="apiname">recv() </span> to
wake up until all 250 bytes of data have arrived.</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"><h4 class="sectiontitle">Socket flow of events: Requests from either IPv4 or IPv6 clients</h4><div class="note"><span class="notetitle">Note:</span> This
client example can be used with other server application designs that want
to accept request for either IPv4 or IPv6 nodes. Other server designs can
be used with this client example.</div>
<ol><li>The <span class="apiname">inet_pton()</span> call converts the text
form of the address to the binary form. In this example, two of these calls
are issued. The first determines if the server is a valid AF_INET address.
The second <span class="apiname">inet_pton()</span> call determines whether the server
has an AF_INET6 address. If it is numeric, <span class="apiname">getaddrinfo()</span> should
be prevented from doing any name resolution. Otherwise a host name was provided
that needs to be resolved when the <span class="apiname">getaddrinfo()</span> call is
issued.</li>
<li>The <span class="apiname">getaddrinfo()</span> call retrieves the address information
needed for the subsequent <span class="apiname">socket()</span> and <span class="apiname">connect()</span> calls.</li>
<li>The <span class="apiname">socket()</span> function returns a socket descriptor representing
an endpoint. The statement also identifies the address family, socket type,
and protocol using the information returned from <span class="apiname">getaddrinfo()</span>.</li>
<li>The <span class="apiname">connect()</span> function establishes a connection to
the server regardless of whether the server is IPv4 or IPv6..</li>
<li>The <span class="apiname">send()</span> function sends the data request to the server.</li>
<li>The <span class="apiname">recv()</span> function receives data from the server application.</li>
<li>The <span class="apiname">close()</span> function closes any open socket descriptors.</li>
</ol>
</div>
<div class="section"><p>The following sample code shows the server application for this
scenario. </p>
<p></p>
<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>/**************************************************************************/
/* Header files needed for this sample program */
/**************************************************************************/
#include &lt;stdio.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;arpa/inet.h&gt;
/**************************************************************************/
/* Constants used by this program */
/**************************************************************************/
#define SERVER_PORT 3005
#define BUFFER_LENGTH 250
#define FALSE 0
void main()
{
/***********************************************************************/
/* Variable and structure definitions. */
/***********************************************************************/
int sd=-1, sdconn=-1;
int rc, on=1, rcdsize=BUFFER_LENGTH;
char buffer[BUFFER_LENGTH];
struct sockaddr_in6 serveraddr, clientaddr;
int addrlen=sizeof(clientaddr);
char str[INET6_ADDRSTRLEN];
/***********************************************************************/
/* A do/while(FALSE) loop is used to make error cleanup easier. The */
/* close() of each of the socket descriptors is only done once at the */
/* very end of the program. */
/***********************************************************************/
do
{
/********************************************************************/
/* The socket() function returns a socket descriptor representing */
/* an endpoint. Get a socket for address family AF_INET6 to */
/* prepare to accept incoming connections on. */
/********************************************************************/
if ((sd = socket(AF_INET6, SOCK_STREAM, 0)) &lt; 0)
{
perror("socket() failed");
break;
}
/********************************************************************/
/* The setsockopt() function is used to allow the local address to */
/* be reused when the server is restarted before the required wait */
/* time expires. */
/********************************************************************/
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
(char *)&amp;on,sizeof(on)) &lt; 0)
{
perror("setsockopt(SO_REUSEADDR) failed");
break;
}
/********************************************************************/
/* After the socket descriptor is created, a bind() function gets a */
/* unique name for the socket. In this example, the user sets the */
/* address to in6addr_any, which (by default) allows connections to */
/* be established from any IPv4 or IPv6 client that specifies port */
/* 3005. (that is, the bind is done to both the IPv4 and IPv6 TCP/IP */
/* stacks). This behavior can be modified using the IPPROTO_IPV6 */
/* level socket option IPV6_V6ONLY if required. */
/********************************************************************/
memset(&amp;serveraddr, 0, sizeof(serveraddr));
serveraddr.sin6_family = AF_INET6;
serveraddr.sin6_port = htons(SERVER_PORT);
/********************************************************************/
/* Note: applications use in6addr_any similarly to the way they use */
/* INADDR_ANY in IPv4. A symbolic constant IN6ADDR_ANY_INIT also */
/* exists but can only be used to initialize an in6_addr structure */
/* at declaration time (not during an assignment). */
/********************************************************************/
serveraddr.sin6_addr = in6addr_any;
/********************************************************************/
/* Note: the remaining fields in the sockaddr_in6 are currently not */
/* supported and should be set to 0 to ensure upward compatibility. */
/********************************************************************/
if (bind(sd,
(struct sockaddr *)&amp;serveraddr,
sizeof(serveraddr)) &lt; 0)
{
perror("bind() failed");
break;
}
/********************************************************************/
/* The listen() function allows the server to accept incoming */
/* client connections. In this example, the backlog is set to 10. */
/* This means that the system will queue 10 incoming connection */
/* requests before the system starts rejecting the incoming */
/* requests. */
/********************************************************************/
if (listen(sd, 10) &lt; 0)
{
perror("listen() failed");
break;
}
printf("Ready for client connect().\n");
/********************************************************************/
/* The server uses the accept() function to accept an incoming */
/* connection request. The accept() call will block indefinitely */
/* waiting for the incoming connection to arrive from an IPv4 or */
/* IPv6 client. */
/********************************************************************/
if ((sdconn = accept(sd, NULL, NULL)) &lt; 0)
{
perror("accept() failed");
break;
}
else
{
/*****************************************************************/
/* Display the client address. Note that if the client is */
/* an IPv4 client, the address will be shown as an IPv4 Mapped */
/* IPv6 address. */
/*****************************************************************/
getpeername(sdconn, (struct sockaddr *)&amp;clientaddr, &amp;addrlen);
if(inet_ntop(AF_INET6, &amp;clientaddr.sin6_addr, str, sizeof(str))) {
printf("Client address is %s\n", str);
printf("Client port is %d\n", ntohs(clientaddr.sin6_port));
}
}
/********************************************************************/
/* In this example we know that the client will send 250 bytes of */
/* data over. Knowing this, we can use the SO_RCVLOWAT socket */
/* option and specify that we don't want our recv() to wake up */
/* until all 250 bytes of data have arrived. */
/********************************************************************/
if (setsockopt(sdconn, SOL_SOCKET, SO_RCVLOWAT,
(char *)&amp;rcdsize,sizeof(rcdsize)) &lt; 0)
{
perror("setsockopt(SO_RCVLOWAT) failed");
break;
}
/********************************************************************/
/* Receive that 250 bytes of data from the client */
/********************************************************************/
rc = recv(sdconn, buffer, sizeof(buffer), 0);
if (rc &lt; 0)
{
perror("recv() failed");
break;
}
printf("%d bytes of data were received\n", rc);
if (rc == 0 ||
rc &lt; sizeof(buffer))
{
printf("The client closed the connection before all of the\n");
printf("data was sent\n");
break;
}
/********************************************************************/
/* Echo the data back to the client */
/********************************************************************/
rc = send(sdconn, buffer, sizeof(buffer), 0);
if (rc &lt; 0)
{
perror("send() failed");
break;
}
/********************************************************************/
/* Program complete */
/********************************************************************/
} while (FALSE);
/***********************************************************************/
/* Close down any open socket descriptors */
/***********************************************************************/
if (sd != -1)
close(sd);
if (sdconn != -1)
close(sdconn);
}</pre>
</div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="ip6scen.htm" title="This topic describes a typical situation in which you might want to use the AF_INET6 address family.">Socket scenario: Create an application to accept IPv4 and IPv6 clients</a></div>
</div>
<div class="relref"><strong>Related reference</strong><br />
<div><a href="xcodesigns.htm" title="There are a number of ways that you can design a connection-oriented socket server on the iSeries. These example programs can be used to create your own connection-oriented designs.">Examples: Connection-oriented designs</a></div>
<div><a href="xip6client.htm" title="This sample program can be used with the server application that accepts requests from either IPv4 or IPv6 clients.">Example: IPv4 or IPv6 client</a></div>
</div>
<div class="relinfo"><strong>Related information</strong><br />
<div><a href="../apis/socket.htm">socket()</a></div>
<div><a href="../apis/ssocko.htm">setsockopt()</a></div>
<div><a href="../apis/bind.htm">bind()</a></div>
<div><a href="../apis/listen.htm">listen()</a></div>
<div><a href="../apis/accept.htm">accept()</a></div>
<div><a href="../apis/gpeern.htm">getpeername()</a></div>
<div><a href="../apis/recv.htm">recv()</a></div>
<div><a href="../apis/send.htm">send()</a></div>
<div><a href="../apis/close.htm">close()</a></div>
<div><a href="../apis/inet_pton.htm">inet_pton()</a></div>
<div><a href="../apis/getaddrinfo.htm">getaddrinfo()</a></div>
<div><a href="../apis/connec.htm">connect()</a></div>
</div>
</div>
</body>
</html>