perl網路程式設計

liiinuuux發表於2016-09-26
簡單地發起連線
測試連線ftp埠,將列印220 (vsFTPd 2.2.2)

點選(此處)摺疊或開啟

  1. use Socket;
  2. $proto = getprotobyname('tcp');
  3. my $net_addr = inet_aton("1.1.1.2") or die "aton error $!";
  4. my $sock_addr = sockaddr_in(21, $net_addr) or die "sockaddr error $!";
  5. socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die "sock error ".$!;
  6. connect(SOCK, $sock_addr) or die "connect error $!";
  7. $ret = <SOCK>;
  8. print $ret;



與服務端互動
下面例子連線echo服務,客戶端敲什麼,服務端就會返回什麼。

點選(此處)摺疊或開啟

  1. use Socket;
  2. use IO::Handle;

  3. my $host = "server2";
  4. my $port = getservbyname("echo", "tcp");
  5. my $proto = getprotobyname("tcp");
  6. $host = inet_aton($host) or die "$host: $!";
  7. socket(SOCK, AF_INET, SOCK_STREAM, $proto) or die "socket: $!";
  8. my $sock_addr = sockaddr_in($port, $host);
  9. connect(SOCK, $sock_addr) or die "connect: $!";
  10. SOCK->autoflush(1); 開啟autoflush模式,可以讓客戶端將資訊立刻發出,而不是快取起來。

  11. my $b_out = 0;
  12. my $b_in = 0;

  13. while(my $msg_out = <>)
  14. {
  15.      print SOCK $msg_out;
  16.      my $msg_in = <SOCK>;
  17.      print $msg_in;
  18.      $b_out += length($msg_out);
  19.      $b_in += length($msg_in);
  20.      last unless $b_out < 10;
  21. }
  22. close SOCK;
  23. say "sent $b_out, recived $b_in";



實現簡單的echo服務端

點選(此處)摺疊或開啟

  1. use 5.010;
  2. use Socket;
  3. use IO::Handle;
  4. my $port = 4444;
  5. my $proto = getprotobyname("tcp");
  6. socket(SOCK, AF_INET, SOCK_STREAM, $proto) or die "socket: $!";
  7. setsockopt(SOCK, SOL_SOCKET, OS_REUSEADDR, 1); 允許服務端崩潰後立刻重新使用以繫結的地址
  8. my $sock_addr = sockaddr_in($port, inet_aton("0.0.0.0"));或者my $sock_addr = sockaddr_in($port, INADDR_ANY);
  9. bind(SOCK, $sock_addr);
  10. listen(SOCK, SOMAXCONN);
  11. say "listen ok";
  12. while(1)
  13. {
  14.         my $remote_addr = accept(CONN, SOCK);
  15.         my $pid = fork();
  16.         next unless $pid == 0;
  17.         my($re_port, $re_addr) = sockaddr_in($remote_addr);
  18.         say "connection from ".inet_ntoa($re_addr).":$re_port";
  19.         CONN->autoflush(1);
  20.         while(<CONN>)
  21.         {
  22.                 chomp;
  23.                 print CONN reverse."\n";
  24.         }
  25.         say "connection finished from ".inet_ntoa($re_addr).":$re_port";
  26.         close CONN;
  27. }
  28. close SOCK;




用IO::Socket實現的daytime客戶端

點選(此處)摺疊或開啟

  1. use IO::Socket qw(:DEFAULT :crlf); 匯出crlf常量和預設常量
  2. my $host = "server2";
  3. $/ = CRLF; 設定行尾分隔符為常量CRLF
  4. my $socket = IO::Socket::INET->new("$host:daytime") or die "socket: $!";
  5. chomp (my $time = $socket->getline);
  6. say $time;


IO::Socket::INET的建構函式很強大,比如這種形式

點選(此處)摺疊或開啟

  1. my $socket = IO::Socket::INET->new(PeerAddr=>"server2",
  2.         PeerPort=>"daytime(7)",
  3.         Type=>SOCK_STREAM,
  4.         Proto=>"tcp") or die "socket: $!";

監聽本地埠:

點選(此處)摺疊或開啟

  1. my $listen = IO::Socket::INET->new(
  2.      LocalPort=>"4444",
  3.      Type=>SOCK_STREAM,
  4.      Proto=>"tcp",
  5.      Listen=>128) 監聽佇列長度
  6.      or die "socket: $!"



用物件導向方式實現echo服務端

點選(此處)摺疊或開啟

  1. use 5.010;
  2. use IO::Socket qw(:DEFAULT :crlf);

  3. $/ = CRLF;
  4. my $sock = IO::Socket::INET->new
  5.      (
  6.      Listen => 128,
  7.      LocalPort => 4444,
  8.      Reuse => 1,
  9.      Timeout => 60*60
  10.      )
  11.      or die "socet: $!";
  12. say "listen ok";
  13. while (1)
  14. {
  15.      next unless my $session = $sock->accept;
  16.      next unless fork eq 0;
  17.      my $peer = gethostbyaddr($session->peeraddr, AF_INET) || $session->peerhost;
  18.      my $port = $session->peerport;
  19.      say "connection from [$peer : $port]";
  20.     
  21.      while(<$session>)
  22.      {
  23.           chomp;
  24.           if($_ eq "quit" or $_ eq "exit") {last};
  25.           my $out = reverse;
  26.           print $session $out;
  27.      }
  28.      say "connection from [$peer : $port] finished";
  29.      close $session;
  30. }
  31. close $sock;


用物件導向風格實現客戶端,要求能同時輸入和輸出
例如實現一個telnet客戶端,連線ftp埠

點選(此處)摺疊或開啟

  1. use strict;
  2. use 5.010;

  3. use IO::Socket qw(:DEFAULT :crlf);
  4. sub to_server
  5. {
  6.      my $server = shift;
  7.      while(<>)
  8.      {
  9.           chomp;
  10.           print $server $_.CRLF;
  11.      }
  12. }

  13. sub from_server
  14. {
  15.      my $server = shift;
  16.      $/ = CRLF;
  17.      while(<$server>)
  18.      {
  19.           chomp;
  20.           say;
  21.      }
  22. }

  23. my $sock = IO::Socket::INET->new("server2:21");
  24. my $child = fork;
  25. if($child)
  26. {
  27.      to_server $sock;
  28.      $sock->shutdown(1);
  29.      sleep;
  30. }
  31. else
  32. {
  33.      from_server $sock;
  34.      say "connection closed by foreign host.";
  35. }

執行
[root@server2 pl]# ./a.pl
220 (vsFTPd 2.2.2)
USER anonymous
331 Please specify the password.
PASS asd
230 Login successful.
help
214-The following commands are recognized.
ABOR ACCT ALLO APPE CDUP CWD  DELE EPRT EPSV FEAT HELP LIST MDTM MKD
MODE NLST NOOP OPTS PASS PASV PORT PWD  QUIT REIN REST RETR RMD  RNFR
RNTO SITE SIZE SMNT STAT STOR STOU STRU SYST TYPE USER XCUP XCWD XMKD
XPWD XRMD
214 Help OK.
quit
221 Goodbye.
connection closed by foreign host.










來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26239116/viewspace-2125608/,如需轉載,請註明出處,否則將追究法律責任。

相關文章