?? rhl54.htm
字號(hào):
* 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>
<P>In the case of connection-oriented protocols, the server performs the following functions:
<BR>
<UL>
<LI>Creates a socket with a call to the socket() function.
<BR>
<BR>
<LI>Binds itself to an address with the bind() function call.
<BR>
<BR>
<LI>Listens for connections with the listen() function call.
<BR>
<BR>
<LI>Accepts any incoming requests with the accept() function call.
<BR>
<BR>
<LI>Gets incoming messages with the read() function and replies back with the write() call.
<BR>
<BR>
</UL>
<P>Now let's look at the client side of things in Listing 54.2.
<BR>
<P>
<FONT COLOR="#000080"><B>Listing 54.2. Client side function.</B></FONT>
<BR>
<PRE>
<FONT COLOR="#000080">#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <linux/net.h>
#define MY_PORT 6545
#define MY_HOST_ADDR "204.25.13.1"
int getServerSocketId()
{
int fd, len;
struct sockaddr_in unix_addr;
/* create a Unix domain stream socket */
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
return(-1);
}
/* fill socket address structure w/our address */
memset(&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 *) &unix_addr, len) < 0)
return(-2);
memset(&unix_addr, 0, sizeof(unix_addr));
if (connect(fd, (struct sockaddr *) &unix_addr, len) < 0)
return(-3);
return(fd);
}</FONT></PRE>
<P>The client for connection-oriented communication also takes the following steps:
<BR>
<UL>
<LI>Creates a socket with a call to the socket() function.
<BR>
<BR>
<LI>Attempts to connect to the server with a connect() call.
<BR>
<BR>
<LI>If a connection is made, requests for data with the write() call, and reads incoming replies with the read() function.
<BR>
<BR>
</UL>
<BR>
<A NAME="E69E540"></A>
<H4 ALIGN=CENTER>
<CENTER>
<FONT SIZE=4 COLOR="#FF0000"><B>Connectionless Socket Programming</B></FONT></CENTER></H4>
<BR>
<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 recvfrom() instead of the listen and accept calls. Also, to reply to
messages, the server uses the sendto() function call. See Listing 54.3 for the server side.
<BR>
<P>
<FONT COLOR="#000080"><B>Listing 54.3. The server side.</B></FONT>
<BR>
<PRE>
<FONT COLOR="#000080">#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <linux/net.h>
#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) < 0)
{
myabort("Unable to create socket");
}
bzero((char *)&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 *)&servaddr,sizeof(struct sockaddr)) < 0)
{
myabort("Unable to bind socket");
}
for (;;)
{
/* wait here */
n = recvfrom(sockfd, mesg, MAXM, 0,
(struct sockaddr *)&clientInfo,
sizeof(struct sockaddr));
doSomethingToIt(mesg);
sendto(sockfd,mesg,n,0,
(struct sockaddr *)&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. However, you have to 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.
<BR>
<P>The client does not have to call the connect() system call either. Instead, the client can call the sendto() function directly. The client side is identical to the server side, with the exception that the sendto call is made before the recvfrom() call.
<BR>
<PRE>
<FONT COLOR="#000080">#include <sys/types.h>
#include <sys/socket.h>
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>
<BLOCKQUOTE>
<BLOCKQUOTE>
<HR ALIGN=CENTER>
<BR>
<NOTE>If you are a BSD user, use the sendto() call, do not use sendmsg() call. The sendto() call is more efficient.</NOTE>
<BR>
<HR ALIGN=CENTER>
</BLOCKQUOTE></BLOCKQUOTE>
<P>Any errors are indicated by a return value of -1. Only local errors are detected.
<BR>
<P>The recvfrom() system call is defined as follows:
<BR>
<PRE>
<FONT COLOR="#000080">#include <sys/types.h>
#include <sys/socket.h>
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 may return immediately or wait forever, depending on the type of the flag being set. You can even set time out values. Check the man pages for recvfrom for
more information.
<BR>
<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, published in 1990 by Prentice Hall. This book is a classic used in universities and is, by far, the most detailed book to date.
<BR>
<BR>
<A NAME="E68E417"></A>
<H3 ALIGN=CENTER>
<CENTER>
<FONT SIZE=5 COLOR="#FF0000"><B>Record and File Locking</B></FONT></CENTER></H3>
<BR>
<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.
<BR>
<P>The technique is simple to implement. What usually happens is that a "lock file" is created with the same name as the original file but with the extension .lock, 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.
<BR>
<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.
<BR>
<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 file locking, of course.
<BR>
<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 are locked, so the program has to note the start of the locking region and the length of it,
and then store that information somewhere other processes can examine it.
<BR>
<P>Writing either file locking or record locking code requires a good understanding of the operating system, but is otherwise not difficult, especially because there are thousands of programs readily available from the Internet, in networking programming
books, and on BBSes to examine for example code.
<BR>
<BR>
<A NAME="E68E418"></A>
<H3 ALIGN=CENTER>
<CENTER>
<FONT SIZE=5 COLOR="#FF0000"><B>Interprocess Communications</B></FONT></CENTER></H3>
<BR>
<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.
<BR>
<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 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.
<BR>
<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 they accomplish
the task.
<BR>
<BR>
<A NAME="E68E419"></A>
<H3 ALIGN=CENTER>
<CENTER>
<FONT SIZE=5 COLOR="#FF0000"><B>Summary</B></FONT></CENTER></H3>
<BR>
<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.
<P ALIGN=LEFT>
<A HREF="rhl53.htm" tppabs="http://202.113.16.101/%7eeb%7e/Red%20Hat%20Linux%20Unleashed/rhl53.htm" TARGET="_self"><IMG SRC="purprev.gif" tppabs="http://202.113.16.101/%7eeb%7e/Red%20Hat%20Linux%20Unleashed/purprev.gif" WIDTH = 32 HEIGHT = 32 BORDER = 0 ALT="Previous Page"></A>
<A HREF="#I0" TARGET="_self"><IMG SRC="purtop.gif" tppabs="http://202.113.16.101/%7eeb%7e/Red%20Hat%20Linux%20Unleashed/purtop.gif" WIDTH = 32 HEIGHT = 32 BORDER = 0 ALT="Page Top"></A>
<A HREF="index-1.htm" tppabs="http://202.113.16.101/%7eeb%7e/Red%20Hat%20Linux%20Unleashed/index.htm" TARGET="_self"><IMG SRC="purtoc.gif" tppabs="http://202.113.16.101/%7eeb%7e/Red%20Hat%20Linux%20Unleashed/purtoc.gif" WIDTH = 32 HEIGHT = 32 BORDER = 0 ALT="TOC"></A>
<A HREF="rhl55.htm" tppabs="http://202.113.16.101/%7eeb%7e/Red%20Hat%20Linux%20Unleashed/rhl55.htm" TARGET="_self"><IMG SRC="purnext.gif" tppabs="http://202.113.16.101/%7eeb%7e/Red%20Hat%20Linux%20Unleashed/purnext.gif" WIDTH = 32 HEIGHT = 32 BORDER = 0 ALT="Next Page"></A>
</BODY></HTML>
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -