Here is a Client/Server connection sample for remote function calls in Java. Map data structures are used to wrap parameters and results. All serializable types are supported in function calls which include String, Vector, and ImageIcon. Multithreading is used to allow multiple client requests simultaneously./*-------------------------------------------- $ java ClientMap4 connecting... socketOut socketIn cmd:login1 writeObject(input:login1) readObject()->output output:LOGIN1 output1:user output2:passwd cmd: */ import java.util.concurrent.*; // Executors import java.util.*; // Vector import java.net.*; // Socket, ServerSocket import java.io.*; // InputStream,InputStreamReader,BufferedReader // OutputStream,PrintWriter import javax.swing.ImageIcon; public class ClientMap4 { final int defaultPort = 1234; static BufferedReader consoleIn; // 控制台輸入流 static PrintStream consoleOut; // 控制台輸出流 static Socket skt; static ObjectInputStream socketIn; // 連線插座輸入流 static ObjectOutputStream socketOut; // 連線插座輸出流 @SuppressWarnings("unchecked") public static void main(String args[]) throws Exception { int port = 1234; if(args.length==1) // 命令列有給埠號參數 port = new Integer(args[0]).intValue(); // 則依命令列埠號 consoleOut = System.err; consoleIn = new BufferedReader(new InputStreamReader(System.in)); consoleOut.printf("connecting...\n"); skt = new Socket("localhost",port); consoleOut.printf("socketOut\n"); OutputStream socketOs = skt.getOutputStream(); socketOut = new ObjectOutputStream(socketOs); consoleOut.printf("socketIn\n"); InputStream socketIs = skt.getInputStream(); socketIn = new ObjectInputStream(socketIs); Map<String, Object> packetOut; Map<String, Object> packetIn; while(true) { String cmd,parm1="user",parm2="passwd"; String output=null,output1=null,output2=null; // 測試字串陣列容器 Vector<String> parm = new Vector<String>(); parm.add(parm1); parm.add(parm2); // 測試結果集容器 Vector<Vector<String>> vecResultSet = new Vector<Vector<String>>(); Vector<String> record1 = new Vector<String>(); record1.add("user_id_1"); record1.add("passwod_1"); record1.add("email_1"); Vector<String> record2 = new Vector<String>(); record2.add("user_id_2"); record2.add("passwod_2"); record2.add("email_2"); vecResultSet.add(record1); vecResultSet.add(record2); // 測試圖片 ImageIcon pic = new ImageIcon("test.jpg"); consoleOut.printf("cmd:"); cmd = consoleIn.readLine(); packetOut = new HashMap<String, Object>(); packetOut.put("cmd",cmd); packetOut.put("parm1",parm1); packetOut.put("parm2",parm2); packetOut.put("parm",parm); packetOut.put("vecResultSet",vecResultSet); packetOut.put("pic", pic); consoleOut.printf("writeObject(input:%s)\n",cmd); socketOut.writeObject(packetOut); socketOut.flush(); consoleOut.printf("readObject()->output\n"); packetIn = (Map<String, Object>) socketIn.readObject(); output = (String) packetIn.get("output"); output1 = (String) packetIn.get("output1"); output2 = (String) packetIn.get("output2"); consoleOut.printf("output:%s\n",output); consoleOut.printf("output1:%s\n",output1); consoleOut.printf("output2:%s\n",output2); } } }
/*-------------------------------------------------- $ java ServerMap4 ListenTask: thread:pool-1-thread-1 (9) waiting at port:1234 ServiceTask: thread: pool-1-thread-1 (9) serving /127.0.0.1:59626 ServiceTask: socketOut ServiceTask: socketIn ServiceTask: end of constructor ListenTask: thread:pool-1-thread-1 (9) waiting at port:1234 begin running waiting input cmd=<login1> parm1=<user> parm2=<passwd> parm=<[user, passwd]> vecResultSet=<[[user_id_1, passwod_1, email_1], [user_id_2, passwod_2, email_2]]> pic=width:728,height:90,write to 'test2.jpg' output=<LOGIN1> output1=<user> output2=<passwd> waiting input */ import java.util.concurrent.*; // Executors import java.util.*; // 用到 Vector import java.net.*; // 用到 Socket, ServerSocket import java.io.*; // 用到 InputStream,InputStreamReader,BufferedReader // OutputStream,PrintWriter import javax.imageio.ImageIO; import javax.swing.ImageIcon; import java.awt.Image; import java.awt.image.BufferedImage; import java.awt.Graphics2D; class ServiceTask implements Runnable { BufferedReader consoleIn; // 控制台輸入流 PrintStream consoleOut; // 控制台輸出流 Socket skt; ObjectInputStream socketIn; // 連線插座輸入流 ObjectOutputStream socketOut; // 連線插座輸出流 String host; String port; public ServiceTask(Socket skt) throws IOException { // 取得螢幕輸出流 consoleOut = System.err; // 由連線插座,取得主機,埠號 this.skt = skt; host = skt.getInetAddress().toString(); port = String.valueOf(skt.getPort()); consoleOut.printf("ServiceTask: thread: %s (%d) serving %s:%s\n", Thread.currentThread().getName(), Thread.currentThread().getId(), host,port); // 由連線插座,取得插座輸出入資料流 consoleOut.printf("ServiceTask: socketOut\n"); OutputStream socketOs = skt.getOutputStream(); socketOut = new ObjectOutputStream(socketOs); consoleOut.printf("ServiceTask: socketIn\n"); InputStream socketIs = skt.getInputStream(); socketIn = new ObjectInputStream(socketIs); consoleOut.printf("ServiceTask: end of constructor\n"); } @SuppressWarnings("unchecked") public void run() { consoleOut.printf("\tbegin running\n"); Map<String, Object> packetOut; Map<String, Object> packetIn; // 測試字串陣列容器,結果集容器,圖片 Vector<String> parm; Vector<Vector<String>> vecResultSet; ImageIcon pic; try { // 進行多次對話,直到輸出為QUIT為止 while(true) { consoleOut.printf("\twaiting input\n"); packetIn = (Map<String, Object>) socketIn.readObject(); String cmd = (String) packetIn.get("cmd"); String parm1 = (String) packetIn.get("parm1"); String parm2 = (String) packetIn.get("parm2"); parm = (Vector<String>) packetIn.get("parm"); vecResultSet = (Vector<Vector<String>>)packetIn.get("vecResultSet"); pic = (ImageIcon) packetIn.get("pic"); consoleOut.printf("\tcmd=<%s>\n",cmd); consoleOut.printf("\tparm1=<%s>\n",parm1); consoleOut.printf("\tparm2=<%s>\n",parm2); consoleOut.printf("\tparm=<%s>\n",parm); consoleOut.printf("\tvecResultSet=<%s>\n",vecResultSet); consoleOut.printf("\tpic=width:%d,height:%d,write to '%s'\n",pic.getIconWidth(),pic.getIconHeight(),"test2.jpg"); // save image for comparison Image img = pic.getImage(); BufferedImage bi = new BufferedImage(img.getWidth(null),img.getHeight(null),BufferedImage.TYPE_INT_RGB); Graphics2D g2 = bi.createGraphics(); g2.drawImage(img, 0, 0, null); g2.dispose(); ImageIO.write(bi, "jpg", new File("test2.jpg")); String output = cmd.toUpperCase(); String output1 = parm1; String output2 = parm2; packetOut = new HashMap<String, Object>(); packetOut.put("output",output); packetOut.put("output1",output1); packetOut.put("output2",output2); socketOut.writeObject(packetOut); socketOut.flush(); consoleOut.printf("\toutput=<%s>\n",output); consoleOut.printf("\toutput1=<%s>\n",output1); consoleOut.printf("\toutput2=<%s>\n",output2); if(cmd.equals("quit")) break; // 遇到quit指令結束 } } catch(Exception e) { consoleOut.printf("ServiceTask: exception:%s\n",e); } finally { // 關閉插座資料流和插座本身 try { socketIn.close(); socketOut.close(); skt.close(); } catch(IOException e) { consoleOut.printf("ServiceTask: socket close error:%s\n",e); } } } } class ListenTask implements Runnable { int listenPort; // 監聽埠號 ServerSocket listenSocket; // 監聽插座 PrintStream consoleOut; // 控制台輸出流 ExecutorService pool; // 緒池 public ListenTask(ExecutorService pool, int port) throws IOException { this.listenPort = port; this.pool = pool; consoleOut = System.err; // 建立監聽插座,可能丟例外 listenSocket = new ServerSocket(listenPort); Runnable listenTask = this; Future f = pool.submit(listenTask); } // 監聽緒工作 public void run() { Socket connectedSocket=null; try { while(true) { // 等待新連線 consoleOut.printf("ListenTask: thread:%s (%d) waiting at port:%d\n", Thread.currentThread().getName(), Thread.currentThread().getId(),listenPort); connectedSocket = listenSocket.accept(); // 啟動專屬緒,為新連線服務 Runnable serviceTask = new ServiceTask(connectedSocket); pool.execute(serviceTask); } } catch(IOException e) { consoleOut.printf("ListenTask: accept raised IOException:%s\n",e); System.exit(0); } } } public class ServerMap4 { final int defaultPort = 1234; final ExecutorService pool; public ServerMap4(int port) { pool = Executors.newCachedThreadPool(); // 建立緒池 //pool = Executors.newFixedThreadPool(10); try { if(port < 1024) port = defaultPort; ListenTask listenTask = new ListenTask(pool,port); // 開監聽緒 } catch(IOException e) { System.err.printf("ServerMap4: %s\n", e); } } public static void main(String args[]) throws Exception { int port = -1; if(args.length==1) // 命令列有給埠號參數 port = new Integer(args[0]).intValue(); // 則依命令列埠號 new ServerMap4(port); // 啟動監聽及服務緒 } }
2013年7月5日 星期五
object transfer over Internet in Java
訂閱:
文章 (Atom)