ch59.htm

来自「linux-unix130.linux.and.unix.ebooks130 l」· HTM 代码 · 共 1,177 行 · 第 1/2 页

HTM
1,177
字号


servaddr.sin_family = AF_INET;



servaddr.sin_addr.s_addr = htonl(INADDR_ANY);



servaddr.sin_family = htons(MY_PORT);







/*



* The htonl (for a long integer) and htons (for short integer) convert



* a host oriented byte order * into a network order.



*/











if (bind(sockfd,(struct sockaddr *)&servaddr,sizeof(struct sockaddr)) < 0)



    {



    myabort("Unable to bind socket");



    }







listen(sockfd,5);



for (;;)



    {



    /* wait here */



    newfd=accept(sockfd,(struct sockaddr *)&clientInfo,



            sizeof(struct sockaddr);



    if (newfd < 0)



        {



        myabort("Unable to accept on socket");



        }







    if ((cpid = fork()) < 0)



        {



        myabort("Unable to fork on accept");



        }



    else if (cpid == 0) {  /* child */



        close(sockfd); /* no need for original */



        do_your_thing(newfd);



        exit(0);



        }



        close(newfd); /* in the parent */



}



</FONT></PRE>







<PRE><FONT COLOR="#0066FF">}



</FONT></PRE>



<P>In the case of connection-oriented protocols, the server performs the following



functions:







<UL>



	<LI>Creates a socket with a call to the <TT>socket()</TT> function



	<P>



	<LI>Binds itself to an address with the <TT>bind()</TT> function call



	<P>



	<LI>Listens for connections with the <TT>listen()</TT> function call



	<P>



	<LI>Accepts any incoming requests with the <TT>accept()</TT> function call



	<P>



	<LI>Gets incoming messages with the <TT>read()</TT> function and replies with the



	<TT>write()</TT> call



</UL>







<P>Now let's look at the client side of things, in Listing 59.2.



<H3 ALIGN="CENTER"><A NAME="Heading12<FONT COLOR="#000077">Listing 59.2. The



client side function.</FONT><FONT COLOR="#0066FF"></FONT></H3>



<PRE><FONT COLOR="#0066FF">#include    &lt;sys/types.h&gt;



#include    &lt;sys/socket.h&gt;



#include &lt;linux/in.h&gt;



#include &lt;linux/net.h&gt;







#define MY_PORT 6545



#define MY_HOST_ADDR &quot;204.25.13.1&quot;







int getServerSocketId()



{



    int fd, len;



    struct sockaddr_in   unix_addr;



                /* create a Unix domain stream socket */



    if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) &lt; 0)



        {



        return(-1);



        }



#ifdef LINUX



opt = 1; len = sizeof(opt);



setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&amp;opt,&amp;len);



#endif







                /* fill socket address structure w/our address */



    memset(&amp;unix_addr, 0, sizeof(unix_addr));



    unix_addr.sin_family = AF_INET;







    /* convert internet address to binary value*/



    unix_addr.sin_addr.s_addr = inet_addr(MY_HOST_ADDR);



    unix_addr.sin_family = htons(MY_PORT);







    if (bind(fd, (struct sockaddr *) &amp;unix_addr, len) &lt; 0)



        return(-2);



    memset(&amp;unix_addr, 0, sizeof(unix_addr));



    if (connect(fd, (struct sockaddr *) &amp;unix_addr, len) &lt; 0)



        return(-3);







    return(fd);







}



</FONT></PRE>



<P>The client for connection-oriented communication also takes the following steps:







<UL>



	<LI>Creates a socket with a call to the <TT>socket()</TT> function



	<P>



	<LI>Attempts to connect to the server with a <TT>connect()</TT> call



	<P>



	<LI>If a connection is made, requests data with the <TT>write()</TT> call, and reads



	incoming replies with the <TT>read()</TT> function



</UL>







<H4 ALIGN="CENTER"><A NAME="Heading13<FONT COLOR="#000077">Connectionless Socket



Programming</FONT></H4>



<P>Now let's consider the case of a connectionless exchange of information. The principle



on the server side is different from the connection-oriented server side in that



the server calls <TT>recvfrom()</TT> rather than the <TT>listen</TT> and <TT>accept</TT>



calls. Also, to reply to messages, the server uses the <TT>sendto()</TT> function



call. See Listing 59.3 for the server side.



<H3 ALIGN="CENTER"><A NAME="Heading14<FONT COLOR="#000077">Listing 59.3. The



server side.</FONT><FONT COLOR="#0066FF"></FONT></H3>



<PRE><FONT COLOR="#0066FF">#include    &lt;sys/types.h&gt;



#include    &lt;sys/socket.h&gt;



#include &lt;linux/in.h&gt;



#include &lt;linux/net.h&gt;







#define MY_PORT 6545



#define MAXM   4096



char mesg[MAXM];







main(int argc, char *argv[])



{



int sockfd, newfd;



int cpid; /* child id */



struct sockaddr_in servaddr;



struct sockaddr_in clientInfo;







if ((sockfd = socket(AF_INET, SOCK_STREAM, 0) &lt; 0)



    {



    myabort(&quot;Unable to create socket&quot;);



    }



#ifdef LINUX



opt = 1; len = sizeof(opt);



setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&amp;opt,&amp;len);



#endif







bzero((char *)&amp;servaddr, sizeof(servaddr));







servaddr.sin_family = AF_INET;



servaddr.sin_addr.s_addr = htonl(INADDR_ANY);



servaddr.sin_family = htons(MY_PORT);







/*



* The htonl (for a long integer) and htons (for short integer) convert



* a host oriented byte order * into a network order.



*/











if (bind(sockfd,(struct sockaddr *)&amp;servaddr,sizeof(struct sockaddr)) &lt; 0)



    {



    myabort(&quot;Unable to bind socket&quot;);



    }











for (;;)



    {



    /* wait here */



                         n = recvfrom(sockfd, mesg, MAXM, 0,



                         (struct sockaddr *)&amp;clientInfo,



                          sizeof(struct sockaddr));







                     doSomethingToIt(mesg);







                     sendto(sockfd,mesg,n,0,



                     (struct sockaddr *)&amp;clientInfo,



                      sizeof(struct sockaddr));



 }







}



</FONT></PRE>



<P>As you can see, the two function calls to process each message make this an easier



implementation than a connection-oriented one. You must, however, process each message



one at a time because messages from multiple clients can be multiplexed together.



In a connection-oriented scheme, the child process always knows where each message



originated.</P>



<P>The client does not have to call the <TT>connect()</TT> system call either. Instead,



the client can call the <TT>sendto()</TT> function directly. The client side is identical



to the server side, with the exception that the <TT>sendto</TT> call is made before



the <TT>recvfrom()</TT>call:</P>



<PRE><FONT COLOR="#0066FF">#include &lt;sys/types.h&gt;



#include &lt;sys/socket.h&gt;







int sendto((int sockfd,



 const void *message__,  /* the pointer to message */



 int  length, /* of message */



 unsigned  int type, /* of routing, leave 0 */



 const struct sockaddr * client, /* where to send it */



 int length ); /* of sockaddr */



</FONT></PRE>







<DL>



	<DT><FONT COLOR="#0066FF"></FONT></DT>



</DL>











<DL>



	<DD>



<HR>



<A NAME="Heading15<FONT COLOR="#000077"><B>NOTE: </B></FONT>If you are a BSD



	user, use the <TT>sendto()</TT> call, not the <TT>sendmsg()</TT> call. The <TT>sendto()</TT>



	call is more efficient.



<HR>







</DL>







<P>Any errors are indicated by a return value of <TT>-1</TT>. Only local errors are



detected.</P>







<P>The <TT>recvfrom()</TT> system call is defined as shown here:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">#include &lt;sys/types.h&gt;



#include &lt;sys/socket.h&gt;







int recvfrom(int sockfd,



 const void *message__,  /* the pointer to message */



 int  length, /* of message */



 unsigned  int flags, /* of routing, leave 0 */



 const struct sockaddr * client, /* where to send it */



 int length ); /* of sockaddr */



</FONT></PRE>



<P>If a message is too long to fit in the supplied buffer, the extra bytes are discarded.



The call might return immediately or wait forever, depending on the type of the flag



being set. You can even set timeout values. Check the man pages for <TT>recvfrom</TT>



for more information.</P>



<P>There you have it--the very basics of how to program applications to take advantage



of the networking capabilities under Linux. We have not even scratched the surface



of all the intricacies of programming for networks. A good starting point for more



detailed information would be UNIX Network Programming, by W. Richard Stevens (Prentice



Hall, 1990). This book, a classic, is used in most universities and is by far the



most detailed book to date.



<H3 ALIGN="CENTER"><A NAME="Heading16<FONT COLOR="#000077">Record and File



Locking</FONT></H3>



<P>When two processes want to share a file, the danger exists that one process might



affect the contents of the file, and thereby affect the other process. For this reason,



most operating systems use a mutually exclusive principle: when one process has a



file open, no other process can touch it. This is called file locking.</P>



<P>This technique is simple to implement. What usually happens is that a &quot;lock



file&quot; is created with the same name as the original file but with the extension



<TT>.lock</TT>, which tells other processes that the file is unavailable. This is



how many Linux spoolers, such as the print system and UUCP, implement file locking.



It is a brute-force method, perhaps, but effective and easy to program.</P>



<P>Unfortunately, this technique is not good when you must have several processes



access the same information quickly, because the delays waiting for file opening



and closing can grow to be appreciable. Also, if one process doesn't release the



file properly, other processes can hang there, waiting for access.</P>



<P>For this reason, record locking is sometimes implemented. With record locking,



a single part of a larger file is locked to prevent two processes from changing its



contents at the same time. Record locking enables many processes to access the same



file at the same time, each updating different records within the file, if necessary.



The programming necessary to implement record locking is more complex than that for



file locking, of course.</P>



<P>Normally, to implement record locking, you use a file offset, or the number of



characters from the beginning of the file. In most cases, a range of characters is



locked; the program has to note the start of the locking region and the length of



it, and then store that information where other processes can examine it.</P>



<P>Writing either file-locking or record-locking code requires a good understanding



of the operating system but is otherwise not difficult, especially because thousands



of programs are readily available from the Internet, in networking programming books,



and on BBSs to examine for sample code.



<H3 ALIGN="CENTER"><A NAME="Heading17<FONT COLOR="#000077">Interprocess Communications</FONT></H3>



<P>Network programming always involves two or more processes talking to each other



(interprocess communications), so the way in which processes communicate is vitally



important to network programmers. Network programming differs from the usual method



of programming in a few important aspects. A traditional program can talk to different



modules (or even other applications on the same machine) through global variables



and function calls. That doesn't work across networks.</P>



<P>A key goal of network programming is to ensure that processes don't interfere



with each other. Otherwise, systems can get bogged down or can lock up. Therefore,



processes must have a clean and efficient method of communicating. UNIX is particularly



strong in this regard, because many of the basic UNIX capabilities, such as pipes



and queues, are used effectively across networks.</P>



<P>Writing code for interprocess communications is quite difficult compared to single



application coding. If you want to write this type of routine, you should study sample



programs from a network programming book or a BBS site to see how this task is accomplished.



<H3 ALIGN="CENTER"><A NAME="Heading18<FONT COLOR="#000077">Summary</FONT></H3>



<P>Few people need to write network applications, so the details of the process are



best left to those who want them. Experience and lots of examples are the best way



to begin writing network code, and mastering the skills can take many years.



















</td>
</tr>
</table>

<!-- begin footer information -->



</body></html>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?