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

📄 ch17_11.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
字号:
<HTML><HEAD><TITLE>Recipe 17.10. Writing Bidirectional Clients (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:44:35Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch17_01.htm"TITLE="17. Sockets"><LINKREL="prev"HREF="ch17_10.htm"TITLE="17.9. Closing a Socket After Forking"><LINKREL="next"HREF="ch17_12.htm"TITLE="17.11. Forking Servers"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch17_10.htm"TITLE="17.9. Closing a Socket After Forking"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 17.9. Closing a Socket After Forking"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch17_01.htm"TITLE="17. Sockets"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch17_12.htm"TITLE="17.11. Forking Servers"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 17.11. Forking Servers"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch17-14110">17.10. Writing Bidirectional Clients</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch17-pgfId-1106">Problem<ACLASS="indexterm"NAME="ch17-idx-1000004793-0"></A><ACLASS="indexterm"NAME="ch17-idx-1000004793-1"></A><ACLASS="indexterm"NAME="ch17-idx-1000004793-2"></A></A></H3><PCLASS="para">You want set up a fully interactive client so you can type a line, get the answer, type a line, get the answer, etc., somewhat like <EMCLASS="emphasis">telnet</EM>.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch17-pgfId-1112">Solution</A></H3><PCLASS="para">Once you've connected, fork off a duplicate process. One twin only reads your input and passes it on to the server, and the other only reads the server's output and sends it to your own output.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch17-pgfId-1118">Discussion</A></H3><PCLASS="para">In a client-server relationship, it is difficult to know whose turn it is to talk. Single-threaded solutions involving the four-argument version of <CODECLASS="literal">select</CODE> are hard to write and maintain. But there's no reason to ignore multitasking solutions. The <CODECLASS="literal">fork</CODE> function dramatically simplifies this problem.</P><PCLASS="para">Once you've connected to the service you'd like to chat with, call <CODECLASS="literal">fork</CODE> to clone a twin. Each of these two (nearly) identical processes has a simple job. The parent copies everything from the socket to standard output, and the child simultaneously copies everything from standard input to the socket.</P><PCLASS="para">The code is in <ACLASS="xref"HREF="ch17_11.htm#ch17-35420"TITLE="biclient">Example 17.4</A>.</P><DIVCLASS="example"><H4CLASS="example"><ACLASS="title"NAME="ch17-35420">Example 17.4: biclient</A></H4><PRECLASS="programlisting">#!/usr/bin/perl -w# <ACLASS="indexterm"NAME="ch17-idx-1000004800-0"></A>biclient - bidirectional forking client    use strict;use IO::Socket;my ($host, $port, $kidpid, $handle, $line);unless (@ARGV == 2) { die &quot;usage: $0 host port&quot; }($host, $port) = @ARGV;# create a tcp connection to the specified host and port$handle = IO::Socket::INET-&gt;new(Proto     =&gt; &quot;tcp&quot;,                                PeerAddr  =&gt; $host,                                PeerPort  =&gt; $port)       or die &quot;can't connect to port $port on $host: $!&quot;;$handle-&gt;autoflush(1);              # so output gets there right awayprint STDERR &quot;[Connected to $host:$port]\n&quot;;# split the program into two processes, identical twinsdie &quot;can't fork: $!&quot; unless defined($kidpid = fork());if ($kidpid) {                          # parent copies the socket to standard output    while (defined ($line = &lt;$handle&gt;)) {        print STDOUT $line;    }    kill(&quot;TERM&quot; =&gt; $kidpid);        # send SIGTERM to child}else {                                  # child copies standard input to the socket    while (defined ($line = &lt;STDIN&gt;)) {        print $handle $line;    }}exit;</PRE></DIV><PCLASS="para">To accomplish the same thing using just one process is remarkably more difficult. It's easier to code two processes, each doing a single task, than it is to code one process to do two different tasks. Take advantage of multitasking by splitting your program into multiple threads of control, and some of your bewildering problems will become much easier.</P><PCLASS="para">The <CODECLASS="literal">kill</CODE> function in the parent's <CODECLASS="literal">if</CODE> block is there to send a signal to the child (currently running in the <CODECLASS="literal">else</CODE> block) as soon as the remote server has closed its end of the connection. The <CODECLASS="literal">kill</CODE> at the end of the parent's block is there to eliminate the child process as soon as the server on the other end goes away.</P><PCLASS="para">If the remote server sends data a byte at time and you need that data immediately without waiting for a newline (which may never arrive), you may wish to replace the <CODECLASS="literal">while</CODE> loop in the parent with the following:</P><PRECLASS="programlisting">my $byte;while (sysread($handle, $byte, 1) == 1) {    print STDOUT $byte;}</PRE><PCLASS="para">Making a system call for each byte you want to read is not very efficient (to put it mildly), but it is the simplest to explain and works reasonably well. <ACLASS="indexterm"NAME="ch17-idx-1000004802-0"></A><ACLASS="indexterm"NAME="ch17-idx-1000004802-1"></A><ACLASS="indexterm"NAME="ch17-idx-1000004802-2"></A></P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch17-pgfId-1214">See Also</A></H3><PCLASS="para">The <ACLASS="olink"HREF="../prog/ch03_166.htm">&#13;<CODECLASS="literal">sysread</CODE></A>and <ACLASS="olink"HREF="../prog/ch03_040.htm">&#13;<CODECLASS="literal">fork</CODE></A>functions in <ACLASS="olink"HREF="../prog/ch03_01.htm">Chapter 3</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A> and in <ICLASS="filename">perlfunc </I>(1); the documentation for the standard IO::Socket module; <ACLASS="xref"HREF="ch16_06.htm"TITLE="Filtering Your Own Output">Recipe 16.5</A>; <ACLASS="xref"HREF="ch16_11.htm"TITLE="Communicating Between Related Processes">Recipe 16.10</A>; <ACLASS="xref"HREF="ch17_12.htm"TITLE="Forking Servers">Recipe 17.11</A></P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch17_10.htm"TITLE="17.9. Closing a Socket After Forking"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 17.9. Closing a Socket After Forking"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch17_12.htm"TITLE="17.11. Forking Servers"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 17.11. Forking Servers"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">17.9. Closing a Socket After Forking</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">17.11. Forking Servers</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font> </p> <map name="library-map"> <area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map> </BODY></HTML>

⌨️ 快捷键说明

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