📄 c-netapi3.html
字号:
</tr><tr valign="top"><td colspan=1 rowspan=1><div class="CellBody"><a name="89802"> </a><b class="routine"><i class="routine">zbufSockRecv</i></b><b>( )</b></div></td><td width="10"> </td><td colspan=1 rowspan=1><div class="CellBody"><a name="89804"> </a>Receive data in a zbuf from a TCP socket.</div></td><td width="10"> </td></tr><tr valign="top"><td colspan=1 rowspan=1><div class="CellBody"><a name="89807"> </a><b class="routine"><i class="routine">zbufSockRecvfrom</i></b><b>( )</b></div></td><td width="10"> </td><td colspan=1 rowspan=1><div class="CellBody"><a name="89809"> </a>Receive a message in a zbuf from a UDP socket.</div></td><td width="10"> </td></tr><tr><td colspan="20"><hr class="tablerule"></td></tr><tr valign="middle"><td colspan="20"></td></tr></table></p></p><dd><p class="Body"><a name="89810"> </a>For a detailed description of each routine, see the corresponding reference entry.</p></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H4"><i><a name="89811">Standard Socket Calls and Zbuf Socket Calls</a></i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="89812"> </a>The zbuf socket calls are particularly useful when large data transfer is a significant part of your socket application. For example, many socket applications contain sections of code like the following fragment:</p><dl class="margin"><dd><pre class="Code2"><b><a name="89813">pBuffer = malloc (BUFLEN); while ((readLen = read (fdDevice, pBuffer, BUFLEN)) > 0) write (fdSock, pBuffer, readLen);</a></b></pre></dl><dd><p class="Body"><a name="89815"> </a>You can eliminate the overhead of copying from the application buffer <b class="symbol_lc">pBuffer</b> into the internal socket buffers by changing the code to use zbuf socket calls. For example, the following fragment is a zbuf version of the preceding loop:</p><dl class="margin"><dd><pre class="Code2"><b><a name="89816">pBuffer = malloc (BUFLEN * BUFNUM); /* allocate memory */ for (ix = 0; ix < (BUFNUM - 1); ix++, pBuffer += BUFLEN) appBufRetn (pBuffer); /* fill list of free bufs */ while ((readLen = read (fdDevice, pBuffer, BUFLEN)) > 0) { zId = zbufCreate (); /* insert into new zbuf */ zbufInsertBuf (zId, NULL, 0, pBuffer, readLen, appBufRetn, 0); zbufSockSend (fdSock, zId, readLen, 0); /* send zbuf */ pBuffer = appBufGet (WAIT_FOREVER); /* get a fresh buffer */ }</a></b></pre></dl><dd><p class="Body"><a name="89827"> </a>The <b class="routine"><i class="routine">appBufGet</i></b><b>( )</b> and <b class="routine"><i class="routine">appBufRetn</i></b><b>( )</b> references in the preceding code fragment stand for application-specific buffer management routines, analogous to <b class="routine"><i class="routine">malloc</i></b><b>( )</b> and <b class="routine"><i class="routine">free</i></b><b>( )</b>. In many applications, these routines do nothing more than manipulate a linked list of free fixed-length buffers.</p></dl></dl><h4 class="EntityTitle"><a name="89829"><font face="Helvetica, sans-serif" size="-1" class="sans">Example 7-5: The TCP Example Server Using Zbufs</font></a></h4><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="89831"> </a>For a small but complete example that illustrates the mechanics of using the zbuf socket library, consider the conversion of the client-server example in <a href="c-netapi2.html#88737">Example 7-1</a> to use zbuf socket calls. </p><dd><p class="Body"><a name="89835"> </a>No conversion is needed for the client side of the example; the client operates the same regardless of whether or not the server uses zbufs. The next example illustrates the following changes to convert the server side to use zbufs:</p></dl><dl class="margin"><p class="listspace"><ul class="Dash" type="circle"><li><a name="89836"> </a>Instead of including the header file <b class="file">sockLib.h</b>, include <b class="file">zbufSockLib.h</b>.</li></ul></p><p class="listspace"><ul class="Dash" type="circle"><li><a name="89837"> </a>The data processing component must be capable of dealing with potentially non-contiguous data in successive zbuf segments. In the TCP example, this component displays a message using <b class="routine"><i class="routine">printf</i></b><b>( )</b>; we can use the <b class="routine"><i class="routine">zbufDisplay</i></b><b>( )</b> routine from <a href="c-netapi3.html#89723">Example 7-4</a> instead.</li></ul></p><p class="listspace"><ul class="Dash" type="circle"><li><a name="89841"> </a>The original TCP example exploits <b class="routine"><i class="routine">fioRead</i></b><b>( )</b> to collect the complete message, rather than calling <b class="routine"><i class="routine">recv</i></b><b>( )</b> directly. To achieve the same end while avoiding data copying by using zbufs, the following example defines a <b class="routine"><i class="routine">zbufFioSockRecv</i></b><b>( )</b> subroutine to call <b class="routine"><i class="routine">zbufSockRecv</i></b><b>( )</b> repeatedly until the complete message is received.</li></ul></p><p class="listspace"><ul class="Dash" type="circle"><li><a name="89842"> </a>A new version of the worker routine <b class="routine"><i class="routine">tcpServerWorkTask</i></b><b>( )</b> must tie together these separate modifications, and must explicitly extract the <b class="symbol_lc">reply</b> and <b class="symbol_lc">msgLen</b> fields from the client's transmission to do so. When using zbufs, these fields cannot be extracted by reference to the C structure in <b class="file">tcpExample.h</b> because of the possibility that the data is not contiguous.</li></ul></p></dl><dl class="margin"><dd><p class="Body"><a name="89843"> </a>The following example shows the auxiliary <b class="routine"><i class="routine">zbufFioSockRecv</i></b><b>( )</b> routine and the zbuf version of <b class="routine"><i class="routine">tcpServerWorkTask</i></b><b>( )</b>. To run this code:</p></dl><dl class="margin"><p><ol class="List"><li value="1."><a name="89847"> </a>Start with <b class="file">tcpServer.c</b> as defined in <a href="c-netapi2.html#88737">Example 7-1</a>.</li></ol></p><p><ol class="List"><li value="2."><a name="89848"> </a>Include the header file <b class="file">zbufSockLib.h</b>.</li></ol></p><p><ol class="List"><li value="3."><a name="89852"> </a>Insert the <b class="routine"><i class="routine">zbufDisplay</i></b><b>( )</b> routine from <a href="c-netapi3.html#89723">Example 7-4</a>.</li></ol></p><p><ol class="List"><li value="4."><a name="89853"> </a>Replace the <b class="routine"><i class="routine">tcpServerWorkTask</i></b><b>( )</b> definition with the following two routines:</li></ol></p></dl><dl class="margin"><dd><pre class="Code"><b><a name="89854">/************************************************************************ * * zbufFioSockRecv - receive <len> bytes from a socket into a zbuf * * This routine receives a specified amount of data from a socket into a * zbuf, by repeatedly calling zbufSockRecv() until <len> bytes * are read. * * RETURNS: * The ID of the zbuf containing <len> bytes of data, * or NULL if there is an error during the zbufSockRecv() operation. * * SEE ALSO: zbufSockRecv() */</a></b><dd> <b><a name="92809">ZBUF_ID zbufFioSockRecv ( int fd, /* file descriptor of file to read */ int len /* maximum number of bytes to read */ ) { BOOL first = TRUE; /* first time thru ? */ ZBUF_ID zRecvTotal = NULL; /* zbuf to return */ ZBUF_ID zRecv; /* zbuf read from sock */ int nbytes; /* number of recv bytes */</a></b><dd> <b><a name="92811"> for (; len > 0; len -= nbytes) { nbytes = len; /* set number of bytes wanted */</a></b><dd> <b><a name="89860"> /* read a zbuf from the socket */</a></b><dd> <b><a name="89862"> if (((zRecv = zbufSockRecv (fd, 0, &nbytes)) == NULL) || (nbytes <= 0)) { if (zRecvTotal != NULL) zbufDelete (zRecvTotal); return (NULL); }</a></b><dd> <b><a name="89864"> /* append recv'ed zbuf onto end of zRecvTotal */</a></b><dd> <b><a name="89865"> if (first) zRecvTotal = zRecv; /* cannot append to empty zbuf */ else if (zbufInsert (zRecvTotal, NULL, ZBUF_END, zRecv) == NULL) { zbufDelete (zRecv); zbufDelete (zRecvTotal); return (NULL); }</a></b><dd> <b><a name="89866"> first = FALSE; /* can append now... */ }</a></b><dd> <b><a name="89867"> return (zRecvTotal); }</a></b><dd> <b><a name="89869">/************************************************************************ * * tcpServerWorkTask - process client requests * * This routine reads from the server's socket, and processes client * requests. If the client requests a reply message, this routine * sends a reply to the client. * * RETURNS: N/A. */</a></b><dd> <b><a name="89871">VOID tcpServerWorkTask ( int sFd, /* server's socket fd */ char * address, /* client's socket address */ u_short port /* client's socket port */ ) { static char replyMsg[] = "Server received your message"; ZBUF_ID zReplyOrig; /* original reply msg */ ZBUF_ID zReplyDup; /* duplicate reply msg */ ZBUF_ID zRequest; /* request msg from client */ int msgLen; /* request msg length */ int reply; /* reply requested ? */</a></b><dd> <b><a name="89873"> /* create original reply message zbuf */</a></b><dd> <b><a name="89874"> if ((zReplyOrig = zbufCreate ()) == NULL) { perror ("zbuf create"); free (address); /* free malloc from inet_ntoa() */ return; }</a></b><dd> <b><a name="89876"> /* insert reply message into zbuf */</a></b><dd> <b><a name="89877"> if (zbufInsertBuf (zReplyOrig, NULL, 0, replyMsg, sizeof (replyMsg), NULL, 0) == NULL) { perror ("zbuf insert"); zbufDelete (zReplyOrig); free (address); /* free malloc from inet_ntoa() */ return; }</a></b><dd> <b><a name="89879"> /* read client request, display message */</a></b><dd> <b><a name="89880"> while ((zRequest = zbufFioSockRecv (sFd, sizeof(struct request))) != NULL) { /* extract reply field into <reply> */</a></b><dd> <b><a name="89882"> (void) zbufExtractCopy (zRequest, NULL, 0, (char *) &reply, sizeof (reply)); (void) zbufCut (zRequest, NULL, 0, sizeof (reply));</a></b><dd> <b><a name="89884"> /* extract msgLen field into <msgLen> */</a></b><dd> <b><a name="89886"> (void) zbufExtractCopy (zRequest, NULL, 0, (char *) &msgLen, sizeof (msgLen)); (void) zbufCut (zRequest, NULL, 0, sizeof (msgLen));</a></b><dd> <b><a name="89888"> /* duplicate reply message zbuf, preserving original */</a></b><dd> <b><a name="89890"> if ((zReplyDup = zbufDup (zReplyOrig, NULL, 0, ZBUF_END)) == NULL) { perror ("zbuf duplicate"); zbufDelete (zRequest); break; }</a></b><dd> <b><a name="89892"> printf ("MESSAGE FROM CLIENT (Internet Address %s, port %d):\n", address, port); /* display request message zbuf */</a></b><dd> <b><a name="89894"> (void) zbufDisplay (zRequest, NULL, 0, msgLen, TRUE); printf ("\n"); if (reply) { if (zbufSockSend (sFd, zReplyDup, sizeof (replyMsg), 0) < 0) perror ("zbufSockSend"); }</a></b><dd> <b><a name="89896"> /* finished with request message zbuf */</a></b><dd> <b><a name="89898"> zbufDelete (zRequest); }</a></b><dd> <b><a name="89900"> free (address); /* free malloc from inet_ntoa() */ zbufDelete (zReplyOrig); close (sFd); }</a></b></pre></dl></dl><dl class="margin"><dd><p class="table" callout><table border="0" cellpadding="0" cellspacing="0"><tr valign="top"><td valign="top" width="40"><br><img border="0" alt="*" src="icons/caution.gif"></td><td><hr><div class="CalloutCell"><a name="93513"><b class="symbol_UC"><font face="Helvetica, sans-serif" size="-1" class="sans">CAUTION: </font></b></a>In the interests of brevity, the <b class="symbol_UC">STATUS</b> return values for several zbuf socket calls are discarded with casts to <b class="keyword">void</b>. In a real application, check these return values for possible errors. </div></td></tr><tr valign="top"><td></td><td><hr></td></tr><tr valign="middle"><td colspan="20"></td></tr></table></p callout></dl><a name="foot"><hr></a><p class="navbar" align="right"><a href="index.html"><img border="0" alt="[Contents]" src="icons/contents.gif"></a><a href="c-netapi.html"><img border="0" alt="[Index]" src="icons/index.gif"></a><a href="c-netapi.html"><img border="0" alt="[Top]" src="icons/top.gif"></a><a href="c-netapi2.html"><img border="0" alt="[Prev]" src="icons/prev.gif"></a><a href="c-dns.html"><img border="0" alt="[Next]" src="icons/next.gif"></a></p></body></html><!---by WRS Documentation (), Wind River Systems, Inc. conversion tool: Quadralay WebWorks Publisher 4.0.11 template: CSS Template, Jan 1998 - Jefro --->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -