Java之~tenlet~篇(使用日本:小高知宏 著的 《TCP/IP Java篇》中的代码)~~外加本人讲解

Java之~tenlet~篇(使用日本:小高知宏 著的 《TCP/IP Java篇》中的代码)~~外加本人讲解

 

  1 /**/ /*
  2 小高知宏 写的书叫《TCP/IP java篇》但我看起来,还想大都是应用层上的东西
  3 好象应该叫《TCP/IP 应用层 java篇》 有点搞不清他的书名是从何而来的,呵呵!
  4 这是小高知宏的Telnet的客户端程序,接下来我们看看它是怎么实现的
  5 */
 
  6
  7 import  java.net. * ;
  8 import  java.io. *
  9
 10 public   class  Telnet  {
 11  Socket serverSocket;                 // 创建服务器端SOCKET
 12   public  OutputStream serverOutput;
 13   public  BufferedInputStream serverInput;
 14  String host;                   // 要连接的telnet服务器的地址或域名
 15   int  port;                      // 要连接的服务器端口 
 16
 17   static   final   int  DEFAULT_TELNET_PORT  =   23 ;   // 定义默认的Telnet端口
 18   
 19    // 构造telnet的连接参数(含端口,就是当你使用23以外的端口时,调用这个函数体),有点像C的数据结构
 20   public  Telnet(String host,  int  port) {
 21    this .host  =  host;     // 这里不解释了THIS的用法前面讲过
 22    this .port  =  port;
 23  }

 24    // 定义默认端口23对应的函数体
 25   public  Telnet(String host) {
 26    this (host, DEFAULT_TELNET_PORT); 
 27
 28   // 建立连接,将在客户端输入的数据host+port转换成数据流
 29   public   void  openConnection()
 30    throws  IOException,UnknownHostException
 31   {                                                                                     
 32   serverSocket  =   new  Socket(host, port);      // 创建Socket                                        
 33   serverOutput  =  serverSocket.getOutputStream();    // 获取输入数据
 34   serverInput  =   new  BufferedInputStream(serverSocket.getInputStream());  // 装换数据
 35    if  (port  ==  DEFAULT_TELNET_PORT) {   // 判断端口是不是23
 36    negotiation(serverInput, serverOutput);  // 对输出和输入的数据进行分析,实现C/S端口的协商
 37   }

 38  }
 
 39
 40   public   void  main_proc()     // 连接成功,启动网络线程
 41    throws  IOException
 42   {
 43    try   {
 44    
 45     // 生成线程的StreamConnector类的对象stdin_to_socket和socket_to_stdout
 46     // 从这里看出java是如何用类去创建对象的
 47    StreamConnector stdin_to_socket  =
 48      new  StreamConnector(System.in, serverOutput);     // StreamConnector这个类在后面有定义
 49    StreamConnector socket_to_stdout  =
 50      new  StreamConnector(serverInput, System.out);
 51    
 52     // 生成对象对应的stdin_to_socket和socket_to_stdout线程事件input_thread和output_thread
 53     // 看到java的事件是如何从对象中产生的
 54    Thread input_thread  =   new  Thread(stdin_to_socket);
 55    Thread output_thread  =   new  Thread(socket_to_stdout);
 56    
 57     // 看看java如何启动或调用事件
 58    input_thread.start();
 59    output_thread.start();
 60   }

 61    // 整个过程可能会产生异常,这里进行捕获
 62    catch (Exception e) {
 63    System.err.print(e);
 64    System.exit( 1 );
 65   }

 66  }

 67    // 定义用于协商的命令
 68     // 如果一个数据既是static又是final,那么他会拥有一块无法改变的存储空间
 69   static   final   byte  IAC  =  ( byte 255 ;
 70   static   final   byte  DONT  =  ( byte 254 ;
 71   static   final   byte  DO  =  ( byte 253 ;
 72   static   final   byte  WONT  =  ( byte 252 ;
 73   static   final   byte  WILL  =  ( byte 251
 74
 75    // 利用NVT进行通信
 76    /**/ /*
 77   NVT是一种抽象的设备,由打印机和键盘组成。用户使用键盘键入的字符被转发到服务器中,
 78   服务器再把数据返回给用户,而NVT在打印机上将其输出。它使用标准的回车与换行组合去
 79   终止行。NVT提供控制操作,这些操作支持过程中断并丢弃多余的输出。这些操作是通过使
 80   用IAC(Interpret as Command,解释成命令)代码发出的。IAC是一个单字节,由值255或十
 81   六进制0xff组成。IAC后面可以跟着一个单字节,用于发送控制代码;或者后面跟着两个或
 82   更多的字节,用于协商一选项。而为了发送已用于IAC的字节值255,可以通过一个特殊的字
 83   节序列来实现:连续发送两个IAC。
 84   JAVA实现应用层的不少东西都是用他实现的 如:HTTP
 85    */

 86   
 87   static   void  negotiation(
 88   BufferedInputStream in,OutputStream out)
 89    throws  IOException
 90   {
 91    byte [] buff  =   new   byte [ 3 ];     // 接收数据
 92    while ( true {
 93    in.mark(buff.length);   // 在此缓冲区的位置设置其标记
 94     if  (in.available()  >=  buff.length)  {
 95     in.read(buff);    // 读取缓冲区内容
 96      if  (buff[ 0 !=  IAC) {   // 协商结束
 97      in.reset();     // 将此缓冲区的位置重新设置成以前标记的位置
 98       return ;
 99     }
  else   if  (buff[ 1 ==  DO)  {     // 用于对DO的回应
100      buff[ 1 =  WONT;
101      out.write(buff);
102     }

103    }

104   }

105  }
 
106
107     // 这里是主函数 
108   public   static   void  main(String[] arg) {
109    try   {
110    Telnet t  =   null ;     // 创建Telnet变量
111     switch  (arg.length) {
112     case   1 :    // 服务器名
113     t  =   new  Telnet(arg[ 0 ]);
114      break ;
115     case   2 :   // 服务器名+端口
116     t  =   new  Telnet(arg[ 0 ], Integer.parseInt(arg[ 1 ]));
117      break ;
118     default :    // 如果输入格式不对
119     System.out.println(
120       " usage: java Telnet <host name> {<port number>} " );
121      return ;
122    }

123    t.openConnection();   // 连接
124    t.main_proc();     // 创建线程
125   }
catch (Exception e) {
126    e.printStackTrace();
127    System.exit( 1 );
128   }

129  }

130 }
 
131
132 // 定义StreamConnector类
133 // 定义前面的对象、事件的具体实现
134 class  StreamConnector  implements  Runnable  {
135  InputStream src  =   null ;
136  OutputStream dist  =   null
137
138 // 接收参数
139   public  StreamConnector(InputStream in, OutputStream out) {
140   src  =  in;
141   dist  =  out;
142  }

143 // 用循环实现对数据流的读写
144   public   void  run() {
145    byte [] buff  =   new   byte [ 1024 ];    // 一次处理的最大数据量
146    while  ( true {
147     try   {
148      int  n  =  src.read(buff);
149      if  (n  >   0 )
150      dist.write(buff,  0 , n);
151    }

152     catch (Exception e) {
153     e.printStackTrace();
154     System.err.print(e);
155     System.exit( 1 );
156    }

157   }

158  }

159 }
 
160


地震让大伙知道:居安思危,才是生存之道。

你可能感兴趣的:(Java之~tenlet~篇(使用日本:小高知宏 著的 《TCP/IP Java篇》中的代码)~~外加本人讲解)