📄 0590-0592.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="0587-0589.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0593-0596.html">Next</A>
</CENTER></P>
<A NAME="PAGENUM-590"><P>Page 590</P></A>
<P>UDP, like SOCK_DGRAM, is connectionless and unreliable. Applications have to provide
whatever reliability mechanisms are necessary for the job that they are performing. For some
applications, that is an advantage because all the mechanisms provided by TCP aren't always
needed. For example, DNS, which uses UDP, simply sends a message and waits for a response for
a predetermined interval; because DNS is a one-to-one message-to-response protocol,
sequencing between client and server is not necessary. UDP is connectionless, so a server can use
one socket to communicate with many clients. All clients write to the same address for the
server, and the server responds individually by writing to specific client addresses.
</P>
<P>UDP messages can also be broadcast to entire networks, which is a blessing to the
application that needs to communicate one message to many users, but a curse for the workstations
that don't need the message but have to read it in order to figure out that it isn't for them.
The ability to broadcast messages over UDP and the fact that the connectionless aspect of
UDP makes it difficult to verify the source of messages are two of the reasons why many
networking people consider the protocol to be a security risk and dislike even enabling it within their
organizations.
</P>
<H4><A NAME="ch28_ 7">
Making a Connection
</A></H4>
<P>Logically, if you are creating a connection like that of the
makeconn() function in Listing 28.1, you need to create a
SOCK_STREAM socket with the TCP protocol information retrieved
with getprotobyname() in line 15. Take a look at lines 27 and 28 from Listing 28.1, repeated here:
</P>
<!-- CODE SNIP //-->
<PRE>27: socket(CONNFD, PF_INET, SOCK_STREAM, $proto);
28: connect(CONNFD, $servaddr) or die "connect : $!";
</PRE>
<!-- END CODE SNIP //-->
<P>After creating the socket in line 27, you then pass it to
connect() with the address structure created by
sockaddr_in(). The connect() function actually contacts the address specified
in the structure and establishes the virtual circuit supported by TCP.
</P>
<H3><A NAME="ch28_ 8">
A TCP Client Example
</A></H3>
<P>Listing 28.3 puts makeconn() to work in a sample program.
client1 can be found on the book's CD-ROM.
</P>
<P>Listing 28.3. client1.
</P>
<!-- CODE //-->
<PRE>#!/usr/bin/perl
use Socket;
require "./network.pl";
$NETFD = makeconn($ARGV[0], $ARGV[1]);
#
# Get the message
#
sysread $NETFD, $message, 32768 or die "error getting message : $!";
print "$message \n";
close $NETFD;
</PRE>
<!-- END CODE //-->
<A NAME="PAGENUM-591"><P>Page 591</P></A>
<P>Run this program with two command-line arguments, the name of a Linux host that is
running sendmail and the mail port name, smtp:
</P>
<!-- CODE SNIP //-->
<PRE>$ ./client1 iest smtp
220 iest.home.mxn.com ESMTP Sendmail 8.8.5/8.8.5; Sat, 4 Oct 1997 18:25:08 -0400
</PRE>
<!-- END CODE SNIP //-->
<P>This program uses makeconn() to connect to the
sendmail program running on the named host and reads the greeting that it sends to a new client when it first connects, using the
sysread() function.
</P>
<P>sysread() is one of the functions used for extracting network messages from sockets. It is
a wrapper for the UNIX read() system call. You cannot use the Perl
read() function because it is designed for standard I/O, which uses buffering and other high-level features that
interfere with network communications. In a real-world application, you would probably read
messages with sysread() in and out of a buffer of your own and keep careful track of what you had
just read because it is possible to be interrupted in a read call by a signal. (You would also
install signal handlers.) As this example demonstrates, establishing a client connection and
retrieving some data is pretty simple.
</P>
<P>
<TABLE BGCOLOR="#FFFF99">
<TR><TD><B>
TIP
</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
One of the benefits of using Perl for network programming is that it hides the issue of
byte ordering between different architectures. Intel
x86 chips and Sun SPARC chips, for example, represent values differently. The creators of the
Internet introduced a concept of network byte
order, which programs are supposed to place values in prior to
transmission and have to translate back to their network format when they read in messages. Perl
does this for us.
</BLOCKQUOTE></TD></TR>
</TABLE></CENTER>
</P>
<H3>
A TCP Server Example
</H3>
<P>Now you'll write your own server for client1 to connect to. First, you have to place a
socket in the listen state. You'll use another function that is defined in
network.pl, makelisten(), which is shown in Listing 28.4.
</P>
<P>Listing 28.4. makelisten().
</P>
<!-- CODE //-->
<PRE> 1: sub makelisten {
2:
3: my ($portname, $port, $proto, $servaddr);
4: $portname = $_[0];
5:
6: #
7: # port and protocol
8: #
9: $port = getservbyname($portname, `tcp') or
</PRE>
<!-- END CODE //-->
<PRE>
continues
</PRE>
<A NAME="PAGENUM-592"><P>Page 592</P></A>
<P>Listing 28.4. continued
</P>
<!-- CODE //-->
<PRE>10: die "getservbyname: cannot get port : $!";
11: $proto = getprotobyname(`tcp') or
12: die "getprotobyname: cannot get proto : $!";
13:
14: #
15: # Bind an inet address
16: #
17: socket(LISTFD, PF_INET, SOCK_STREAM, $proto);
18: bind (LISTFD, sockaddr_in($port, INADDR_ANY)) or die "bind: $!";
19: listen (LISTFD, SOMAXCONN) or die "listen: $!";
20: return LISTFD;
21: }
</PRE>
<!-- END CODE //-->
<P>The makelisten() function creates a TCP socket,
binds it to a local address, and then places it in the
listen state.
</P>
<P>Lines 9 and 11 retrieve the same information that
makeconn() retrieves in order to create a connection, with the exception of an internet address.
makelisten() then creates an internet family
SOCK_STREAM socket, which by definition is a TCP socket, but you specify this
explicitly anyway, as in makeconn().
</P>
<P>In line 18, the socket is bound to a local address. This tells the system that any messages sent
to the specified service port and internet address should be relayed to the specified socket.
You use sockaddr_in() to build an address from the service port retrieved with
getportbyname() and with a special address that corresponds to all addresses on the workstation so that
connections can be made to all network interfaces and even over any dial-up interfaces on the
workstation. This function shows a little laziness in that it passes the
sockaddr_in() function to bind() instead of calling it separately and saving the results.
</P>
<P>There are some restrictions on what service ports can be bound. For historical reasons, only
the programs executing with superuser access can bind service ports numbered lower than 1024.
</P>
<P>After the socket is bound, you can execute
listen(), which notifies the system that you're
ready to accept client connections.
</P>
<P>server1, the program that uses makelisten(), is just as simple as the client and is shown
in Listing 28.5. You can find it on the CD-ROM that accompanies this book.
</P>
<P>Listing 28.5. server1.
</P>
<!-- CODE //-->
<PRE>#!/usr/bin/perl
use Socket;
require "./network.pl";
$hello = "Hello world!";
$LISTFD = makelisten("test");
</PRE>
<!-- END CODE //-->
<P><CENTER>
<a href="0587-0589.html">Previous</A> | <a href="../ewtoc.html">Table of Contents</A> | <a href="0593-0596.html">Next</A>
</CENTER></P>
</td>
</tr>
</table>
<!-- begin footer information -->
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -