⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 0597-0599.html

📁 linux-unix130.linux.and.unix.ebooks130 linux and unix ebookslinuxLearning Linux - Collection of 12 E
💻 HTML
字号:


<HTML>

<HEAD>

<TITLE>Developer.com - Online Reference Library - 0672311739:RED HAT LINUX 2ND EDITION:Network Programming</TITLE>

<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<SCRIPT>
<!--
function displayWindow(url, width, height) {
        var Win = window.open(url,"displayWindow",'width=' + width +
',height=' + height + ',resizable=1,scrollbars=yes');
}
//-->
</SCRIPT>
</HEAD>

 -->




<!-- ISBN=0672311739 //-->

<!-- TITLE=RED HAT LINUX 2ND EDITION //-->

<!-- AUTHOR=DAVID PITTS ET AL //-->

<!-- PUBLISHER=MACMILLAN //-->

<!-- IMPRINT=SAMS PUBLISHING //-->

<!-- PUBLICATION DATE=1998 //-->

<!-- CHAPTER=28 //-->

<!-- PAGES=0583-0604 //-->

<!-- UNASSIGNED1 //-->

<!-- UNASSIGNED2 //-->









<P><CENTER>

<a href="0593-0596.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0600-0602.html">Next</A>

</CENTER></P>



<A NAME="PAGENUM-597"><P>Page 597</P></A>













<P>Listing 28.9. nonblock.

</P>

<!-- CODE //-->

<PRE>1: #!/usr/bin/perl

2: use Socket;

3: use Fcntl;

4: require &quot;./network.pl&quot;;

5: $poke = &quot;yo!&quot;;

6: $NETFD = makeudpcli();

7: fcntl $NETFD, &amp;F_SETFL, O_NONBLOCK or die &quot;Fcntl failed : $!\n&quot;;

8: (rest of file remains the same)

</PRE>

<!-- END CODE //-->









<P>A new module, Fcntl, is added to the program in line 3, which provides an interface to

the fcntl(2) system call. It is used to alter file descriptor properties, such as blocking and how

it handles certain signals. In line 7, the last line of the modifications to

client2, you set the O_NONBLOCK flag for the UDP socket. The rest of the program is unchanged.

</P>









<P>When nonblocking I/O is used, the application designer has to be very careful when

handling errors returned from recv(), send(), and other I/O related functions. When no more data

is available for reading or no more data can be written, these functions return error codes. As

a result, the application has to be prepared to handle some errors as being routine

conditions. This is also true of the C/C++ interfaces.

</P>









<H3><A NAME="ch28_ 11">

I/O Multiplexing with UDP

</A></H3>









<P>Frequently, applications need to maintain more than one socket or file descriptor. For

example, many system services such as Telnet,

rlogin, and FTP are managed by one process on

Linux. In order to do this, the process, inetd, listens for requests for these services by opening a

socket for each one. Other applications, such as Applix, Netscape, and Xemacs, monitor file

descriptors for the keyboard, mouse, and perhaps the network.

</P>









<P>Let's set up an example that monitors the keyboard and a network connection. Listing

28.10 is contained in the file udptalk, which is included on the CD-ROM.

</P>









<P>Listing 28.10. updtalk.

</P>

<!-- CODE //-->

<PRE> 1: #!/usr/bin/perl

 2:

 3: use Socket;

 4: require &quot;./network.pl&quot;;

 5:

 6:  $NETFD = makeudpserv($ARGV[2]);

 7:

 8:  $addr = gethostbyname($ARGV[0]);

 9:  $port = getservbyname($ARGV[1], `udp');

10:

11:  $servaddr = sockaddr_in($port, $addr);

12:

13:  $rin = &quot;&quot;;

14:  vec($rin, fileno(STDIN), 1) = 1;

</PRE>

<!-- END CODE //-->







<PRE>

                                                 continues

</PRE>



<A NAME="PAGENUM-598"><P>Page 598</P></A>













<P>Listing 28.10. continued

</P>

<!-- CODE //-->

<PRE>15:  vec($rin, fileno($NETFD), 1) = 1;

16:

17:  while (1) {

18:

19:     select $ready = $rin, undef, undef, undef;

20:

21:     if (vec($ready, fileno(STDIN), 1) == 1) {

22:       sysread STDIN, $mesg, 256;

23:        send $NETFD, $mesg, 0, $servaddr;

24:     }

25:     if (vec($ready, fileno($NETFD), 1) == 1) {

26:         recv $NETFD, $netmsg, 256, 0;

27:        print &quot;$netmsg&quot;;

28:        $netmsg = &quot;&quot;;

29:     }

30: }

31:   close $NETFD;

</PRE>

<!-- END CODE //-->









<P>In order to test this program it must be run in either two windows on the same system or

on two different systems. At one command-line session, execute the following command,

where iest is the host on which the second command will be run:

</P>



<!-- CODE SNIP //-->

<PRE>$ ./udptalk iest test test1

</PRE>

<!-- END CODE SNIP //-->









<P>On the second host, run the following command, where

iest is the host where the first command was run:

</P>



<!-- CODE SNIP //-->

<PRE>$ ./udptalk iest test1 test

</PRE>

<!-- END CODE SNIP //-->









<P>Each session will wait for keyboard input. Each line that is typed at one program is printed

by the other, after you press Enter.

</P>









<P>In order to perform the two-way communication required for this exercise, both instances

of udptalk have to bind a well-known port. To permit this on a single workstation, the

program accepts two port names as the second and third command-line arguments. For obvious

reasons, two programs cannot register interest in the same port.

</P>









<P>In line 6 of Listing 28.10, udptalk uses

makeudpserv() to create a UDP socket and bind it to

a well-known port. For the examples here, I used 8000 for one copy and 8001 for the other.

</P>









<P>In lines 8_11, you perform the usual procedure for building a network address. This will

be the address to which the keyboard input is written.

</P>









<P>Lines 13_15 build bit vectors in preparation for the

select() function. In Perl, a bit vector is a scalar variable that is handled as an array of bits; in

other words, instead of being evaluated as bytes that add up to characters or numbers, each individual bit is evaluated as a distinct value.

</P>









<P>In line 13, you create a variable ($rin) and tell the Perl interpreter to clear it. You then use

the vec() and fileno() functions to determine the file number for

STDIN (the keyboard) and set

</P>



<A NAME="PAGENUM-599"><P>Page 599</P></A>













<P>that bit in $rin. Then you do the same for the socket created by

makeudpcli(). Therefore, if STDIN uses file descriptor 1 (which is generally the case), the second bit in

$rin is set to 1. (Bit vectors, like other arrays, start numbering indexes at zero.) Fortunately, the

vec() function can be used to read bit vectors also, so you can treat these data structures as opaque (and sleep a

lot better at night for not knowing the details).

</P>









<P>select() is a key function for systems programmers. Unfortunately, it suffers from an

arcane interface that is intimidating in any language. System V UNIX has a replacement,

poll(), that is a little easier to use, but it is not available on Linux or within Perl. The following is the

function description for select():

</P>



<!-- CODE SNIP //-->

<PRE>select readfds, writefds, exceptfds, timeout;

</PRE>

<!-- END CODE SNIP //-->









<P>Like most of the UNIX system interface, this is virtually identical to

select() in C/C++.<BR>

select() is used for discovering which file descriptors are ready for reading, are ready for

writing, or have an exceptional condition. An exceptional condition usually corresponds with

the arrival of what is called out-of-band or urgent data. This sort of data is most frequently

associated with TCP connections. When a message is sent out-of-band, it is tagged as being

more important than any previously sent data and is placed at the top of the data queue. A client

or server can use this to notify the process on the other end of a connection that it is

exiting immediately.

</P>









<P>The first three arguments are bit vectors that correspond to the file descriptors that you

are interested in reading or writing to or that you are monitoring for exceptional conditions.

If you aren't interested in a set of file descriptors, you can pass

undef instead of a vector. In Listing 28.10, you aren't interested in writing or exceptions, so you pass

undef for the second and third arguments.

</P>









<P>When select returns, only the bits that correspond to files with activity are set; if any

descriptors aren't ready when select returns, their settings are lost in the vector. For that reason,

you have select() create a new vector and copy it into

$ready. This is done by passing an assignment to

select() as the first argument in line 19.

</P>









<P>The last parameter is the time-out interval in seconds.

select() waits for activity for this period. If the period expires with no activity occurring,

select() will return with everything in the vector cleared. Because

undef is supplied for timeout in line 19, select() will block until

a file is ready.

</P>









<P>Inside the while loop entered in line 17, you call

select(), passing it the bit vector built earlier and the new one to be created. When it returns, you check the vector using

vec() with pretty much the same syntax as you used to set the bits; however because you are using

== instead of =, vec() returns the value of the bit instead of setting it.

</P>









<P>If the bit for STDIN is set, you read from the keyboard and send it to the other instance of

udptalk. If the bit for the socket is set, you read from it and print it to the terminal. This sequence

illustrates a very important advantage of the sockets interface. The program is extracting data

to and from the network using the same functions as the keyboard and screen.

</P>



<P><CENTER>

<a href="0593-0596.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0600-0602.html">Next</A>

</CENTER></P>









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

<!-- begin footer information -->





</body></html>

⌨️ 快捷键说明

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