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

📄 perlipc.1

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 1
📖 第 1 页 / 共 5 页
字号:
\&\&    socket(Server,PF_UNIX,SOCK_STREAM,0)        || die "socket: $!";\&    unlink($NAME);\&    bind  (Server, $uaddr)                      || die "bind: $!";\&    listen(Server,SOMAXCONN)                    || die "listen: $!";\&\&    logmsg "server started on $NAME";\&\&    my $waitedpid;\&\&    use POSIX ":sys_wait_h";\&    sub REAPER {\&        my $child;\&        while (($waitedpid = waitpid(\-1,WNOHANG)) > 0) {\&            logmsg "reaped $waitedpid" . ($? ? " with exit $?" : \*(Aq\*(Aq);\&        }\&        $SIG{CHLD} = \e&REAPER;  # loathe sysV\&    }\&\&    $SIG{CHLD} = \e&REAPER;\&\&\&    for ( $waitedpid = 0;\&          accept(Client,Server) || $waitedpid;\&          $waitedpid = 0, close Client)\&    {\&        next if $waitedpid;\&        logmsg "connection on $NAME";\&        spawn sub {\&            print "Hello there, it\*(Aqs now ", scalar localtime, "\en";\&            exec \*(Aq/usr/games/fortune\*(Aq or die "can\*(Aqt exec fortune: $!";\&        };\&    }\&\&    sub spawn {\&        my $coderef = shift;\&\&        unless (@_ == 0 && $coderef && ref($coderef) eq \*(AqCODE\*(Aq) {\&            confess "usage: spawn CODEREF";\&        }\&\&        my $pid;\&        if (!defined($pid = fork)) {\&            logmsg "cannot fork: $!";\&            return;\&        } elsif ($pid) {\&            logmsg "begat $pid";\&            return; # I\*(Aqm the parent\&        }\&        # else I\*(Aqm the child \-\- go spawn\&\&        open(STDIN,  "<&Client")   || die "can\*(Aqt dup client to stdin";\&        open(STDOUT, ">&Client")   || die "can\*(Aqt dup client to stdout";\&        ## open(STDERR, ">&STDOUT") || die "can\*(Aqt dup stdout to stderr";\&        exit &$coderef();\&    }.Ve.PPAs you see, it's remarkably similar to the Internet domain \s-1TCP\s0 server, somuch so, in fact, that we've omitted several duplicate functions\*(--\fIspawn()\fR,\&\fIlogmsg()\fR, \fIctime()\fR, and \s-1\fIREAPER\s0()\fR\-\-which are exactly the same as in theother server..PPSo why would you ever want to use a Unix domain socket instead of asimpler named pipe?  Because a named pipe doesn't give you sessions.  Youcan't tell one process's data from another's.  With socket programming,you get a separate session for each client: that's why \fIaccept()\fR takes twoarguments..PPFor example, let's say that you have a long running database server daemonthat you want folks from the World Wide Web to be able to access, but onlyif they go through a \s-1CGI\s0 interface.  You'd have a small, simple \s-1CGI\s0program that does whatever checks and logging you feel like, and then actsas a Unix-domain client and connects to your private server..SH "TCP Clients with IO::Socket".IX Header "TCP Clients with IO::Socket"For those preferring a higher-level interface to socket programming, theIO::Socket module provides an object-oriented approach.  IO::Socket isincluded as part of the standard Perl distribution as of the 5.004release.  If you're running an earlier version of Perl, just fetchIO::Socket from \s-1CPAN\s0, where you'll also find modules providing easyinterfaces to the following systems: \s-1DNS\s0, \s-1FTP\s0, Ident (\s-1RFC\s0 931), \s-1NIS\s0 andNISPlus, \s-1NNTP\s0, Ping, \s-1POP3\s0, \s-1SMTP\s0, \s-1SNMP\s0, SSLeay, Telnet, and Time\*(--justto name a few..Sh "A Simple Client".IX Subsection "A Simple Client"Here's a client that creates a \s-1TCP\s0 connection to the \*(L"daytime\*(R"service at port 13 of the host name \*(L"localhost\*(R" and prints out everythingthat the server there cares to provide..PP.Vb 9\&    #!/usr/bin/perl \-w\&    use IO::Socket;\&    $remote = IO::Socket::INET\->new(\&                        Proto    => "tcp",\&                        PeerAddr => "localhost",\&                        PeerPort => "daytime(13)",\&                    )\&                  or die "cannot connect to daytime port at localhost";\&    while ( <$remote> ) { print }.Ve.PPWhen you run this program, you should get something back thatlooks like this:.PP.Vb 1\&    Wed May 14 08:40:46 MDT 1997.Ve.PPHere are what those parameters to the \f(CW\*(C`new\*(C'\fR constructor mean:.ie n .IP """Proto""" 4.el .IP "\f(CWProto\fR" 4.IX Item "Proto"This is which protocol to use.  In this case, the socket handle returnedwill be connected to a \s-1TCP\s0 socket, because we want a stream-orientedconnection, that is, one that acts pretty much like a plain old file.Not all sockets are this of this type.  For example, the \s-1UDP\s0 protocolcan be used to make a datagram socket, used for message-passing..ie n .IP """PeerAddr""" 4.el .IP "\f(CWPeerAddr\fR" 4.IX Item "PeerAddr"This is the name or Internet address of the remote host the server isrunning on.  We could have specified a longer name like \f(CW"www.perl.com"\fR,or an address like \f(CW"204.148.40.9"\fR.  For demonstration purposes, we'veused the special hostname \f(CW"localhost"\fR, which should always mean thecurrent machine you're running on.  The corresponding Internet addressfor localhost is \f(CW"127.1"\fR, if you'd rather use that..ie n .IP """PeerPort""" 4.el .IP "\f(CWPeerPort\fR" 4.IX Item "PeerPort"This is the service name or port number we'd like to connect to.We could have gotten away with using just \f(CW"daytime"\fR on systems with awell-configured system services file,[\s-1FOOTNOTE:\s0 The system services fileis in \fI/etc/services\fR under Unix] but just in case, we've specified theport number (13) in parentheses.  Using just the number would also haveworked, but constant numbers make careful programmers nervous..PPNotice how the return value from the \f(CW\*(C`new\*(C'\fR constructor is used asa filehandle in the \f(CW\*(C`while\*(C'\fR loop?  That's what's called an indirectfilehandle, a scalar variable containing a filehandle.  You can useit the same way you would a normal filehandle.  For example, youcan read one line from it this way:.PP.Vb 1\&    $line = <$handle>;.Ve.PPall remaining lines from is this way:.PP.Vb 1\&    @lines = <$handle>;.Ve.PPand send a line of data to it this way:.PP.Vb 1\&    print $handle "some data\en";.Ve.Sh "A Webget Client".IX Subsection "A Webget Client"Here's a simple client that takes a remote host to fetch a documentfrom, and then a list of documents to get from that host.  This is amore interesting client than the previous one because it first sendssomething to the server before fetching the server's response..PP.Vb 10\&    #!/usr/bin/perl \-w\&    use IO::Socket;\&    unless (@ARGV > 1) { die "usage: $0 host document ..." }\&    $host = shift(@ARGV);\&    $EOL = "\e015\e012";\&    $BLANK = $EOL x 2;\&    foreach $document ( @ARGV ) {\&        $remote = IO::Socket::INET\->new( Proto     => "tcp",\&                                         PeerAddr  => $host,\&                                         PeerPort  => "http(80)",\&                                        );\&        unless ($remote) { die "cannot connect to http daemon on $host" }\&        $remote\->autoflush(1);\&        print $remote "GET $document HTTP/1.0" . $BLANK;\&        while ( <$remote> ) { print }\&        close $remote;\&    }.Ve.PPThe web server handing the \*(L"http\*(R" service, which is assumed to be atits standard port, number 80.  If the web server you're trying toconnect to is at a different port (like 1080 or 8080), you should specifyas the named-parameter pair, \f(CW\*(C`PeerPort => 8080\*(C'\fR.  The \f(CW\*(C`autoflush\*(C'\fRmethod is used on the socket because otherwise the system would bufferup the output we sent it.  (If you're on a Mac, you'll also need tochange every \f(CW"\en"\fR in your code that sends data over the network tobe a \f(CW"\e015\e012"\fR instead.).PPConnecting to the server is only the first part of the process: once youhave the connection, you have to use the server's language.  Each serveron the network has its own little command language that it expects asinput.  The string that we send to the server starting with \*(L"\s-1GET\s0\*(R" is in\&\s-1HTTP\s0 syntax.  In this case, we simply request each specified document.Yes, we really are making a new connection for each document, even thoughit's the same host.  That's the way you always used to have to speak \s-1HTTP\s0.Recent versions of web browsers may request that the remote server leavethe connection open a little while, but the server doesn't have to honorsuch a request..PPHere's an example of running that program, which we'll call \fIwebget\fR:.PP.Vb 6\&    % webget www.perl.com /guanaco.html\&    HTTP/1.1 404 File Not Found\&    Date: Thu, 08 May 1997 18:02:32 GMT\&    Server: Apache/1.2b6\&    Connection: close\&    Content\-type: text/html\&\&    <HEAD><TITLE>404 File Not Found</TITLE></HEAD>\&    <BODY><H1>File Not Found</H1>\&    The requested URL /guanaco.html was not found on this server.<P>\&    </BODY>.Ve.PPOk, so that's not very interesting, because it didn't find thatparticular document.  But a long response wouldn't have fit on this page..PPFor a more fully-featured version of this program, you should look tothe \fIlwp-request\fR program included with the \s-1LWP\s0 modules from \s-1CPAN\s0..Sh "Interactive Client with IO::Socket".IX Subsection "Interactive Client with IO::Socket"Well, that's all fine if you want to send one command and get one answer,but what about setting up something fully interactive, somewhat likethe way \fItelnet\fR works?  That way you can type a line, get the answer,type a line, get the answer, etc..PPThis client is more complicated than the two we've done so far, but ifyou're on a system that supports the powerful \f(CW\*(C`fork\*(C'\fR call, the solutionisn't that rough.  Once you've made the connection to whatever serviceyou'd like to chat with, call \f(CW\*(C`fork\*(C'\fR to clone your process.  Each ofthese two identical process has a very simple job to do: the parentcopies everything from the socket to standard output, while the childsimultaneously copies everything from standard input to the socket.To accomplish the same thing using just one process would be \fImuch\fRharder, because it's easier to code two processes to do one thing than itis to code one process to do two things.  (This keep-it-simple principlea cornerstones of the Unix philosophy, and good software engineering aswell, which is probably why it's spread to other systems.).PPHere's the code:.PP.Vb 4\&    #!/usr/bin/perl \-w\&    use strict;\&    use IO::Socket;\&    my ($host, $port, $kidpid, $handle, $line);\&\&    unless (@ARGV == 2) { die "usage: $0 host port" }\&    ($host, $port) = @ARGV;\&\&    # create a tcp connection to the specified host and port\&    $handle = IO::Socket::INET\->new(Proto     => "tcp",\&                                    PeerAddr  => $host,\&                                    PeerPort  => $port)\&           or die "can\*(Aqt connect to port $port on $host: $!";\&\&    $handle\->autoflush(1);              # so output gets there right away\&    print STDERR "[Connected to $host:$port]\en";\&\&    # split the program into two processes, identical twins\&    die "can\*(Aqt fork: $!" unless defined($kidpid = fork());\&\&    # the if{} block runs only in the parent process\&    if ($kidpid) {\&        # copy the socket to standard output\&        while (defined ($line = <$handle>)) {\&            print STDOUT $line;\&        }\&        kill("TERM", $kidpid);                  # send SIGTERM to child\&    }\&    # the else{} block runs only in the child process\&    else {\&        # copy standard input to the socket\&        while (defined ($line = <STDIN>)) {\&            print $handle $line;\&        }\&    }.Ve.PPThe \f(CW\*(C`kill\*(C'\fR function in the parent's \f(CW\*(C`if\*(C'\fR block is there to send asignal to our child process (current running in the \f(CW\*(C`else\*(C'\fR block)as soon as the remote server has closed its end of the connection..PPIf the remote server sends data a byte at time, and you need thatdata immediately without waiting for a newline (which might not happen),you may wish to replace the \f(CW\*(C`while\*(C'\fR loop in the parent with thefollowing:.PP.Vb 4\&    my $byte;\&    while (sysread($handle, $byte, 1) == 1) {\&        print STDOUT $byte;\&    }.Ve.PPMaking a system call for each byte you want to read is not very efficient(to put it mildly) but is the simplest to explain and works reasonablywell..SH "TCP Servers with IO::Socket".IX Header "TCP Servers with IO::Socket"As always, setting up a server is little bit more involved than running a client.The model is that the server creates a special kind of socket thatdoes nothing but listen on a particular port for incoming connections.It does this by calling the \f(CW\*(C`IO::Socket::INET\->new()\*(C'\fR method withslightly different arguments than the client did..IP "Proto" 4.IX Item "Proto"This is which protocol to use.  Like our clients, we'llstill specify \f(CW"tcp"\fR here..IP "LocalPort" 4.IX Item "LocalPort"We specify a localport in the \f(CW\*(C`LocalPort\*(C'\fR argument, which we didn't do for the cli

⌨️ 快捷键说明

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