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

Telnet服务器

开发平台:

Unix_Linux

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