tcp.pl.in
上传用户:minyiyu
上传日期:2018-12-24
资源大小:864k
文件大小:13k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. #!@PERL@
  2. #CVS: $Id: tcp.pl.in,v 1.1 2000/01/15 01:45:39 edwardc Exp $
  3. package main;
  4. sub tcp'getostype {
  5.    chop($_=`uname -a`); 
  6.    if ( /^SunOS/i ) {
  7.        ($os,$host,$ver)=split(/s+/,$_);
  8.         if ( $ver =~ /5./ ) {
  9.                 return "Solaris";            
  10.         } else {
  11.                 return "BSD";
  12.         }
  13.    } elsif (/^HP-UX/i) {
  14.         return "SYSV";
  15.    } elsif (/^AIX/i ) {
  16.         return "AIX";
  17.    } elsif (/^OSF1/i) {
  18.         return "SYSV";
  19.    }
  20. }
  21. $tcp'OS = &tcp'getostype();
  22. if ( $OS eq "Solaris") {
  23.       eval 'sub SOCK_STREAM {2;}';
  24.       eval 'sub SOCK_DGRAM {1;}';
  25.     } else {
  26.       eval 'sub SOCK_STREAM {1;}';
  27.       eval 'sub SOCK_DGRAM {2;}';
  28.     }
  29.     eval 'sub SOCK_RAW {3;}';
  30.     eval 'sub SOCK_RDM {4;}';
  31.     eval 'sub SOCK_SEQPACKET {5;}';
  32.     eval 'sub SO_DEBUG {0x0001;}';
  33.     eval 'sub SO_ACCEPTCONN {0x0002;}';
  34.     eval 'sub SO_REUSEADDR {0x0004;}';
  35.     eval 'sub SO_KEEPALIVE {0x0008;}';
  36.     eval 'sub SO_DONTROUTE {0x0010;}';
  37.     eval 'sub SO_BROADCAST {0x0020;}';
  38.     eval 'sub SO_USELOOPBACK {0x0040;}';
  39.     eval 'sub SO_LINGER {0x0080;}';
  40.     eval 'sub SO_OOBINLINE {0x0100;}';
  41.     eval 'sub SO_DONTLINGER {(~ &SO_LINGER);}';
  42.     eval 'sub SO_SNDBUF {0x1001;}';
  43.     eval 'sub SO_RCVBUF {0x1002;}';
  44.     eval 'sub SO_SNDLOWAT {0x1003;}';
  45.     eval 'sub SO_RCVLOWAT {0x1004;}';
  46.     eval 'sub SO_SNDTIMEO {0x1005;}';
  47.     eval 'sub SO_RCVTIMEO {0x1006;}';
  48.     eval 'sub SO_ERROR {0x1007;}';
  49.     eval 'sub SO_TYPE {0x1008;}';
  50.     eval 'sub SOL_SOCKET {0xffff;}';
  51.     eval 'sub AF_UNSPEC {0;}';
  52.     eval 'sub AF_UNIX {1;}';
  53.     eval 'sub AF_INET {2;}';
  54.     eval 'sub AF_IMPLINK {3;}';
  55.     eval 'sub AF_PUP {4;}';
  56.     eval 'sub AF_CHAOS {5;}';
  57.     eval 'sub AF_NS {6;}';
  58.     eval 'sub AF_NBS {7;}';
  59.     eval 'sub AF_ECMA {8;}';
  60.     eval 'sub AF_DATAKIT {9;}';
  61.     eval 'sub AF_CCITT {10;}';
  62.     eval 'sub AF_SNA {11;}';
  63.     eval 'sub AF_DECnet {12;}';
  64.     eval 'sub AF_DLI {13;}';
  65.     eval 'sub AF_LAT {14;}';
  66.     eval 'sub AF_HYLINK {15;}';
  67.     eval 'sub AF_APPLETALK {16;}';
  68.     eval 'sub AF_NIT {17;}';
  69.     eval 'sub AF_802 {18;}';
  70.     eval 'sub AF_OSI {19;}';
  71.     eval 'sub AF_X25 {20;}';
  72.     eval 'sub AF_OSINET {21;}';
  73.     eval 'sub AF_GOSIP {22;}';
  74.     eval 'sub AF_MAX {21;}';
  75.     eval 'sub PF_UNSPEC { &AF_UNSPEC;}';
  76.     eval 'sub PF_UNIX { &AF_UNIX;}';
  77.     eval 'sub PF_INET { &AF_INET;}';
  78.     eval 'sub PF_IMPLINK { &AF_IMPLINK;}';
  79.     eval 'sub PF_PUP { &AF_PUP;}';
  80.     eval 'sub PF_CHAOS { &AF_CHAOS;}';
  81.     eval 'sub PF_NS { &AF_NS;}';
  82.     eval 'sub PF_NBS { &AF_NBS;}';
  83.     eval 'sub PF_ECMA { &AF_ECMA;}';
  84.     eval 'sub PF_DATAKIT { &AF_DATAKIT;}';
  85.     eval 'sub PF_CCITT { &AF_CCITT;}';
  86.     eval 'sub PF_SNA { &AF_SNA;}';
  87.     eval 'sub PF_DECnet { &AF_DECnet;}';
  88.     eval 'sub PF_DLI { &AF_DLI;}';
  89.     eval 'sub PF_LAT { &AF_LAT;}';
  90.     eval 'sub PF_HYLINK { &AF_HYLINK;}';
  91.     eval 'sub PF_APPLETALK { &AF_APPLETALK;}';
  92.     eval 'sub PF_NIT { &AF_NIT;}';
  93.     eval 'sub PF_802 { &AF_802;}';
  94.     eval 'sub PF_OSI { &AF_OSI;}';
  95.     eval 'sub PF_X25 { &AF_X25;}';
  96.     eval 'sub PF_OSINET { &AF_OSINET;}';
  97.     eval 'sub PF_GOSIP { &AF_GOSIP;}';
  98.     eval 'sub PF_MAX { &AF_MAX;}';
  99.     eval 'sub SOMAXCONN {5;}';
  100.     eval 'sub MSG_OOB {0x1;}';
  101.     eval 'sub MSG_PEEK {0x2;}';
  102.     eval 'sub MSG_DONTROUTE {0x4;}';
  103.     eval 'sub MSG_MAXIOVLEN {16;}';
  104.     eval 'sub MSG_MAXIOVLEN {16;}';
  105.     eval 'sub WNOHANG {1;}';
  106.     eval 'sub WUNTRACED {2;}';
  107. #package tcp;
  108. $defaultport = 'nntp';
  109. $defaultserver = 'news.csie.ncu.edu.tw.';
  110. $ENV{'PATH'}='/bin:/usr/ucb:/usr/etc';
  111. # The Internet TCP client algorithm 
  112. # 1. Find the IP address and protocol port number of the server
  113. #    with which communication is desired. (gethostbyname,getservbyname)
  114. # 2. Allocate a socket.  (socket)
  115. # 3. Specify that the connection needs an arbitary, unsed protocol
  116. #    port on the local machine, and allow TCP to choose one. (bind)
  117. # 4. Connect the socket to the server. (connect)
  118. # 5. Communicate with the server using the application-level protocol
  119. #    (this usually involves sending requests and awaiting replies)
  120. # 6. close the connection.
  121. #    
  122. # reference: 
  123. # socket addr, internet style structure for Sun-OS
  124. # include <netinet/in.h>
  125. # struct sockaddr_in {
  126. #   short   sin_family;
  127. #   u_short sin_port;
  128. #   struct  in_addr sin_addr;
  129. #   char    sin_zero[8];
  130. # }
  131. # ( 'S n a4 x8' template for perl pack)
  132. # Usage
  133. # &tcpinetclient(FILEHANDLE[,hostname,portno]);
  134. # for example,
  135. # &tcpinetclient(NNTP,'news.csie.ncu.edu.tw','nntp');
  136. # print NNTP "helprn";
  137. # $_ = <NNTP>;
  138. # print;
  139. sub main'tcpinetclient {
  140.   local(*S,$server,$port)=@_;
  141.   $port = $defaultport unless $port; 
  142.   $server = $defaultserver unless $server; 
  143.   local($hostname);
  144.   chop($hostname = `hostname`);
  145.   local($sockaddr)= 'S n a4 x8';
  146.   local($name,$aliases,$proto)=getprotobyname('tcp');
  147.   local($name,$aliases,$port)=getservbyname($port,'tcp')
  148. unless $port =~ /^d+$/;
  149. #  print "port number in tcpinetclient $portn";
  150.   local($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname);
  151.   local($name, $aliases, $type, $len, $thataddr) = gethostbyname($server);
  152.   socket(S, &main'PF_INET, &main'SOCK_STREAM, $proto) || die "socket: $!";
  153.   local($this) = pack($sockaddr, &main'AF_INET, 0, $thisaddr);
  154. # accept connect from any port (0)   
  155.   local($that) = pack($sockaddr, &main'AF_INET, $port, $thataddr);
  156. # bind(S, $this) || die "bind to $hostname: $!";
  157.   connect(S, $that) || die "connect to $port: $!";
  158.   select(S); $| = 1; select(STDOUT);
  159.   1;
  160. }
  161. # reference: socket for unix domain in Sun-OS
  162. # include <socket.h>
  163. # struct sockaddr {
  164. #   u_short sa_family;
  165. #   char    sa_data[14];
  166. # }
  167. # ('S a14' perl template for perl) 
  168. # usage
  169. # &tcpunixclient(FILEHANDLE,path);
  170. # for example,
  171. # &tcpunixclient(LOCAL,"/tmp/unixsock$$");
  172. #$defaultpath="/tmp/unixsock$$";
  173. $defaultpath='/tmp/sample';
  174. # only 14 chars can be used
  175. sub main'tcpunixclient {
  176.   local(*S,$path)=@_;
  177.   $path = $defaultpath unless $path; 
  178.   local($sockaddr)= 'S a14';
  179.   socket(S, &PF_UNIX, &SOCK_STREAM, 0) || die "socket: $!";
  180.   $that = pack($sockaddr, &AF_INET, $path);
  181.   connect(S, $that) || die "connect to $path: $!";
  182.   select(S); $| = 1; select(STDOUT);
  183.   1;
  184. }
  185. # o Interactive, Connection-Orientd Server
  186. # o Interactive, Connectionless Server
  187. # o Concurrent, Connectionless Server 
  188. #   server repeatedly call "recvform" and let slave use "sendto"
  189. #   to reply the client.
  190. # o concurrent, connection-oriented server algorithm
  191. # Master 1. Create a socket and bind to the well-known address
  192. #     for the service being offered. Leave the socket unconnected
  193. #     (socket,bind)
  194. # Master 2. Place the socket in passive mode, makeing it ready for used
  195. #     by a server. (listen)
  196. # Master 3. Repeatedly call accept to receive the next request from
  197. #     a client, and create a new slave process to handle the  
  198. #     response.  (accept)
  199. # Slave  1. Receive a connection request (i.e., socket for the connection)
  200. #     upon creation.
  201. # Slave  2. Interact with the client using the connection: read request(s)
  202. #     and send back response(s).
  203. # Slave  3. Close the connection and exit. The slave process exits
  204. #     after handling all requests from one client.
  205. #
  206. # Usage
  207. # &tcpinetserver([port-no,service-routine,before,each]);
  208. # for example
  209. # &tcpinetserver(1234,'simple_service');
  210. #
  211. $defaultserverport=1234;
  212. $defaultserviceroutine="simple_service";
  213. sub simple_service {
  214. local(*S)=@_;
  215. while (<S>) {
  216. if (/quit/) {
  217. return(0);
  218. } elsif (/help/) {
  219. print S <<"EOF";
  220. This is a simple sample server r
  221. available command r
  222. help quit r
  223. EOF
  224. } else {
  225. print S "Unknown commandrn";
  226. }
  227. }
  228. }
  229. sub reapchild {
  230. while (waitpid(-1,&WNOHANG|&WUNTRACED)>0) {
  231. # print "reapchildn";
  232. # while (waitpid(-1,&WNOHANG)>0) {
  233. # print "reaping childn";
  234. next;
  235. }
  236. 1;
  237. }
  238. #sub reapchild {
  239. # while (1) {
  240. # $pid = waitpid(-1,&WNOHANG);
  241. # last if ($pid < 1);
  242. # }
  243. #}
  244. sub dokill {
  245. kill 9,0;
  246. }
  247. sub main'tcpinetserver {
  248.   local($port,$service,$before,$each)=@_;
  249.   if ($port != 0) {
  250.     $port = $defaultserverport unless $port; 
  251.   }
  252.   $service = $defaultserviceroutine unless $service; 
  253.   local($sockaddr)= 'S n a4 x8';
  254.   local($name,$aliases,$proto)=getprotobyname('tcp');
  255.   local($name,$aliases,$port)=getservbyname($port,'tcp')
  256. unless $port =~ /^d+$/;
  257.   local(*S,*NS);
  258.   chdir("/");
  259.   socket(S, &PF_INET, &SOCK_STREAM, $proto) || die "socket: $!";
  260.   setsockopt(S,main'SOL_SOCKET,main'SO_REUSEADDR,1);
  261.   setsockopt(S,main'SOL_SOCKET,main'SO_LINGER,0);
  262.   if ($port == 0) {
  263.     local($hostname); 
  264.     chop($hostname = `hostname`);
  265.     local($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname);
  266.   } else {
  267. $thisaddr = "";
  268.   }
  269.   $this = pack($sockaddr, &AF_INET, $port, $thisaddr);
  270.   # can accept connection from $port, to any port in client
  271.   bind(S, $this) || die "bind: $!";
  272.   select(S); $| = 1; select(STDOUT);
  273.   $SIG{'CHLD'} = 'reapchild';
  274.   $SIG{'HUP'} = 'IGNORE';
  275.   $SIG{'INT'} = 'dokill';
  276.   $SIG{'TERM'} = 'dokill';
  277.   do $before(S) if ($before);
  278.   listen(S, 5) || die "connect: $!";
  279.   for (;;) {
  280. #    print "Listening againn";
  281.     ($addr = accept(NS,S)) || next;  
  282. # || die "accept: $!n";
  283.     select(NS); $| = 1; select(STDOUT);
  284. #    print "accept okn";
  285.     ($af,$port,$inetaddr) = unpack($sockaddr,$addr);
  286.     @inetaddr = unpack('C4',$inetaddr);
  287. #    print "$af $port @inetaddrn";
  288.     FORK: {
  289. last if ( $pid = fork) ;
  290.   if (defined $pid) {
  291. close(S);
  292.      $return = do $service(NS);
  293. close(NS);
  294. exit($return);
  295. }
  296. if ($! =~ /No more process/) {
  297. sleep 5;
  298. redo FORK;
  299. } else {
  300. die "Can't fork: $!n";
  301. }
  302.     } # FORK
  303.     do $each(NS) if ($each);
  304.     close(NS);
  305.   } # listen forever and fork a client to handle service request
  306. } # end tcpinetserver
  307. # single proecess, connection-oriented server for internet
  308. sub main'tcpinetsingleserver {
  309.   local($port,$service,$beforeservice,$each)=@_;
  310.   if ( $port != 0) {
  311.     $port = $defaultserverport unless $port; 
  312.   }
  313.   $service = $defaultserviceroutine unless $service; 
  314.   local($sockaddr)= 'S n a4 x8';
  315.   local($name,$aliases,$proto)=getprotobyname('tcp');
  316.   local($name,$aliases,$port)=getservbyname($port,'tcp')
  317. unless $port =~ /^d+$/;
  318.   local(*S,*NS);
  319.   chdir("/");
  320.   socket(S, &PF_INET, &SOCK_STREAM, $proto) || die "socket: $!";
  321.   if ($port == 0) {
  322.     local($hostname); 
  323.     chop($hostname = `hostname`);
  324.     local($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname);
  325.   } else {
  326. $thisaddr = "";
  327.   }
  328.   $this = pack($sockaddr, &AF_INET, $port, $thisaddr);
  329.   # can accept connection from $port, to any port in client
  330.   bind(S, $this) || die "bind: $!";
  331.   select(S); $| = 1; select(STDOUT);
  332.   $SIG{'CHLD'} = 'reapchild';
  333.   $SIG{'HUP'} = 'IGNORE';
  334.   $SIG{'INT'} = 'dokill';
  335.   do $beforeservice(S) if ($beforeservice);
  336.   listen(S, 5) || die "connect: $!";
  337.   for (;;) {
  338. #    print "Listening again in single servern";
  339.     ($addr = accept(NS,S)) || next;  
  340.     select(NS); $| = 1; select(STDOUT);
  341. #    print "accept okn";
  342.     ($af,$port,$inetaddr) = unpack($sockaddr,$addr);
  343.     @inetaddr = unpack('C4',$inetaddr);
  344. #    print "$af $port @inetaddrn";
  345.     $return = do $service(NS);
  346.     do $each(NS) if ($each);
  347.     close(NS);
  348.   }
  349. }
  350. # Concurrent, Connection-oriented server for UNIX domain
  351. $path=$defaultpath;
  352. sub doremove {
  353. unlink $path;
  354. kill 9,0;
  355. }
  356. sub simple_unixservice {
  357. local(*S)=@_;
  358. while (<S>) {
  359. if (/quit/) {
  360. return(0);
  361. } elsif (/help/) {
  362. print S <<"EOF";
  363. This is a simple sample server r
  364. available command r
  365. help quit r
  366. EOF
  367. } else {
  368. print S "Unknown commandrn";
  369. }
  370. }
  371. }
  372. sub main'tcpunixserver {
  373.   ($path,$service)=@_;
  374.   $path = $defaultpath unless $path; 
  375.   $service = 'simple_unixservice' unless $service; 
  376.   local($sockaddr)= 'S a14';
  377.   socket(S, &PF_UNIX, &SOCK_STREAM, 0) || die "socket: $!";
  378.   $this = pack($sockaddr, &AF_INET, $path);
  379.   bind(S, $this) || die "bind: $!";
  380.   select(S); $| = 1; select(STDOUT);
  381.   $SIG{'CHLD'} = 'reapchild';
  382.   $SIG{'HUP'} = 'IGNORE';
  383.   $SIG{'INT'} = 'doremove';
  384.   $SIG{'TERM'} = 'doremove';
  385.   for (;;) {
  386.     listen(S, 5) || die "connect: $!";
  387. #    print "Listening againn";
  388.     ($addr = accept(NS,S)) || next;
  389.     select(NS); $| = 1; select(STDOUT);
  390. #    print "accept okn";
  391.     FORK: {
  392. last if ( $pid = fork) ;
  393.   if (defined $pid) {
  394. close(S);
  395.      $return = do $service(NS);
  396. close(NS);
  397. exit($return);
  398. }
  399. if ($! =~ /No more process/) {
  400. sleep 5;
  401. redo FORK;
  402. } else {
  403. die "Can't fork: $!n";
  404. }
  405.     } # FORK
  406.     close(NS);
  407.  }
  408. }
  409. sub main'simpleunixclient {
  410. local($path)= @_;
  411. local(*S,$rin,$rout);
  412. ($path)= $defaultpath unless $path;
  413. &tcpunixclient(S,$path) || die "can't connect: $!n";
  414. $rin='';
  415. vec($rin,fileno(STDIN),1)=1;
  416. vec($rin,fileno(S),1)=1;
  417. for (;;) {
  418. (($nf=select($rout=$rin,undef,undef,undef))>=0) || die "select: $!n";
  419. if (vec($rout,fileno(S),1)) {
  420. $i=read(S,$n,1);
  421. if ($i) {
  422. print $n;
  423. } else {
  424. print "byen";
  425. last;
  426. }
  427. }
  428. if (vec($rout,fileno(STDIN),1)) {
  429. $_ = <STDIN>;
  430. chop;
  431. print S $_,"rn";
  432. }
  433. }
  434. }
  435. sub main'remotehostname {
  436.     (*WNRP) = @_;
  437.     local($there,$here)=(getpeername(WNRP),getsockname(WNRP));
  438.     local($sockaddr)= 'S n a4 x8';
  439.     local($family,$thisport,$thisaddr)=unpack($sockaddr,$here);
  440.     local($family,$thatport,$thataddr)=unpack($sockaddr,$there);
  441.     local(@localaddr)=unpack('C4',$thisaddr);
  442.     local(@remoteaddr)=unpack('C4',$thataddr);
  443.     local($hostname)=gethostbyaddr($thisaddr,&AF_INET);
  444.     local($remotehostname)=gethostbyaddr($thataddr,&AF_INET);
  445.     return ($remotehostname);
  446. }