Java 網路程式設計 -- Telnet

Java 網路程式

簡介

IP

URL

UDP

TCP

Telnet

WebServer

網頁下載

網路爬蟲

Proxy

瀏覽器

訊息

相關網站

參考文獻

最新修改

簡體版

English

在本文中,我們設計了一個稱為 Telnet.java 的程式,以實作 Telnet 的功能。該程式同時是 Client 端,也是 Server 端,因此其架構上是一個 P2P 的程式。

使用時,必須先用 java Telnet server 指令執行伺服端,然後再用 java Telnet <server_ip> 指令執行 Client 端,如此就可以在 Client 端對伺服端下指令,就好像 Server 端的電腦完全受到 Client 端操控一般。其程式如以下的 Telnet.java 所示。

程式: Telnet.java

import java.net.*;
import java.io.*;
 
/* Protocol :    Client ----------- Server
 *
 *                       <---------  <path> (single line)
 * (single line)  <cmd>  ---------->
 *                       <---------  <output> (several lines)
 *                         <---------     ==end== (single line)
 *
 *                another session started again
 *
 *                       <---------  <path> (single line)
 *                       .....
 */
 
public class Telnet {
    static int port = 23;
    static final String endMsg = "==end==";
 
    public static void main(String[] args) throws Exception {
        if (args[0].equals("server"))
            runServer();
        else if (args[0].equals("client"))
            runClient(args[1], port);
        else
            System.out.println("Client : java Telnet client ip\r\n"+
                               "Server : java Telnet server");
    }    
 
    public static void runClient(String host, int port) throws Exception {
        System.out.println("Host " + host + "; port " + port);
        Socket socket = new Socket(host, port);
        new CommandClient(socket).start();
        System.out.println("Connected OK");
    }
 
    public static void runServer() throws Exception {
        ServerSocket server = new ServerSocket(port);  // 建立ServerSocket物件
        while (true)
        {  // 建立客戶端Socket物件
            Socket socket = server.accept();
            System.out.println("Accept Connection From : " + socket.getInetAddress());
            new CommandServer(socket).start();
        }
    }    
}
 
class Command {
    ProcessBuilder pb;
 
    Command() {
        pb = new ProcessBuilder();
        pb.directory(new File("."));
    }
 
    public String exec(String command) throws Exception {
        String outMsg = "", errMsg = "";
        if (command.startsWith("cd ")) {
            String path = command.substring(3);
            if (path.equals("\\")) {
                String tPath = getPath();
                String rootPath = tPath.substring(0,3);
                File root = new File(rootPath);
                pb.directory(root);
            } else {            
                try {
                    File dir = new File(pb.directory(), path);
                    pb.directory(dir);
                } catch (Exception e) {
                    errMsg = "Error: "+e.toString();
                }
            }
        } else {
            String[] cmd = { "cmd.exe", "/C", command };
            pb.command(cmd);
            Process process = pb.start();
             // 取得命令執行的結果串流結果傳回給 Client.
            //   請注意 process.getInputStream() 取得的是 command 的輸出串流,
            //  被重導到輸入串流以利讀取的結果 (這在概念上很怪,但確實如此)
            outMsg = readAll(process.getInputStream());
 
             // 取得命令執行的錯誤串流結果傳回給 Client.
            errMsg = readAll(process.getErrorStream());
            process.waitFor();                     // 等待命令執行完畢
        }
        return outMsg+errMsg;
    }
 
    public String getPath() throws Exception {
        return pb.directory().getCanonicalPath();
    }
 
    public String readAll(InputStream is) throws Exception {
        StringBuffer rzText = new StringBuffer();
        BufferedReader in = new BufferedReader(new InputStreamReader(is));
        String line;
        while ((line = in.readLine()) != null) {
            rzText.append(line+"\r\n");
        }
        return rzText.toString();
    }         
}
 
class CommandServer extends Thread {
    Socket socket;
    BufferedReader in;
    PrintStream out;
    Command command;
 
    public CommandServer(Socket s) throws Exception {
        socket = s;
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new PrintStream(socket.getOutputStream());
        command = new Command();
    }
 
    public void run() {
      try {
         while (true) {
             out.println(command.getPath());     // set path to client
            out.flush();
             String cmd = in.readLine();            // read command from client
             System.out.println(socket.getInetAddress()+" $ "+cmd);
             String rzMsg = command.exec(cmd);    // execute command
             out.print(rzMsg);
            out.println(Telnet.endMsg);            // 輸出結束訊息
            out.flush();
        }
      } catch (Exception e) { e.printStackTrace(); }
    }
}
 
class CommandClient extends Thread {
    Socket socket;
    BufferedReader in, stdin;
    PrintStream out;
 
    public CommandClient(Socket s) throws Exception {
        socket = s;
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new PrintStream(socket.getOutputStream());
        stdin = new BufferedReader(new InputStreamReader(System.in));
    }
 
    public void run() {
      try {
        System.out.println("Accept from : " + socket.getInetAddress());
         while (true) {
             String path = in.readLine();        // read path from server
             System.out.print(socket.getInetAddress()+" $ "+path+">");
             String cmd = stdin.readLine();        // read command from console
             out.println(cmd);                    // send command to server
             while (true) {                        // read output of command from server
                 String line = in.readLine();
                 if (line.equals(Telnet.endMsg))
                     break;
                 System.out.println(line);
             }
        }
      } catch (Exception e) { e.printStackTrace(); }
    }
}

執行結果

編譯

D:\java>javac Telnet.java

伺服端:Telnet Server

D:\java>java Telnet server
Accept Connection From : /127.0.0.1
/127.0.0.1 $ SET JAVA_HOME
/127.0.0.1 $ dir Telnet.java

伺服端:Telnet Client 127.0.0.1

D:\java>java Telnet client 127.0.0.1
Host 127.0.0.1; port 23
Connected OK
Accept from : /127.0.0.1
/127.0.0.1 $ D:\java>SET JAVA_HOME
JAVA_HOME=C:\Program Files\liftweb-1.0.1\jre
/127.0.0.1 $ D:\java>dir Telnet.java
 磁碟區 D 中的磁碟沒有標籤。
 磁碟區序號:  AC7E-23A4

 D:\java 的目錄

2007/05/16  上午 11:23             4,862 Telnet.java
               1 個檔案           4,862 位元組
               0 個目錄   8,863,780,864 位元組可用

Facebook

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License