2013年7月5日 星期五

object transfer over Internet in Java

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.

  1.  
  2. /*--------------------------------------------
  3. $ java ClientMap4
  4. connecting...
  5. socketOut
  6. socketIn
  7. cmd:login1
  8. writeObject(input:login1)
  9. readObject()->output
  10. output:LOGIN1
  11. output1:user
  12. output2:passwd
  13. cmd:
  14. */
  15. import java.util.concurrent.*; // Executors
  16. import java.util.*; // Vector
  17. import java.net.*; // Socket, ServerSocket
  18. import java.io.*; // InputStream,InputStreamReader,BufferedReader
  19. // OutputStream,PrintWriter
  20. import javax.swing.ImageIcon;
  21.  
  22. public class ClientMap4
  23. {
  24. final int defaultPort = 1234;
  25.  
  26. static BufferedReader consoleIn; // 控制台輸入流
  27. static PrintStream consoleOut; // 控制台輸出流
  28.  
  29. static Socket skt;
  30. static ObjectInputStream socketIn; // 連線插座輸入流
  31. static ObjectOutputStream socketOut; // 連線插座輸出流
  32.  
  33. @SuppressWarnings("unchecked")
  34. public static void main(String args[]) throws Exception
  35. {
  36. int port = 1234;
  37.  
  38. if(args.length==1) // 命令列有給埠號參數
  39. port = new Integer(args[0]).intValue(); // 則依命令列埠號
  40.  
  41. consoleOut = System.err;
  42. consoleIn = new BufferedReader(new InputStreamReader(System.in));
  43. consoleOut.printf("connecting...\n");
  44.  
  45. skt = new Socket("localhost",port);
  46.  
  47. consoleOut.printf("socketOut\n");
  48. OutputStream socketOs = skt.getOutputStream();
  49. socketOut = new ObjectOutputStream(socketOs);
  50.  
  51. consoleOut.printf("socketIn\n");
  52. InputStream socketIs = skt.getInputStream();
  53. socketIn = new ObjectInputStream(socketIs);
  54.  
  55. Map<String, Object> packetOut;
  56. Map<String, Object> packetIn;
  57.  
  58.  
  59. while(true)
  60. {
  61. String cmd,parm1="user",parm2="passwd";
  62. String output=null,output1=null,output2=null;
  63.  
  64. // 測試字串陣列容器
  65. Vector<String> parm = new Vector<String>();
  66. parm.add(parm1);
  67. parm.add(parm2);
  68.  
  69. // 測試結果集容器
  70. Vector<Vector<String>> vecResultSet = new Vector<Vector<String>>();
  71. Vector<String> record1 = new Vector<String>();
  72. record1.add("user_id_1");
  73. record1.add("passwod_1");
  74. record1.add("email_1");
  75. Vector<String> record2 = new Vector<String>();
  76. record2.add("user_id_2");
  77. record2.add("passwod_2");
  78. record2.add("email_2");
  79. vecResultSet.add(record1);
  80. vecResultSet.add(record2);
  81.  
  82. // 測試圖片
  83. ImageIcon pic = new ImageIcon("test.jpg");
  84.  
  85. consoleOut.printf("cmd:");
  86. cmd = consoleIn.readLine();
  87. packetOut = new HashMap<String, Object>();
  88. packetOut.put("cmd",cmd);
  89. packetOut.put("parm1",parm1);
  90. packetOut.put("parm2",parm2);
  91. packetOut.put("parm",parm);
  92. packetOut.put("vecResultSet",vecResultSet);
  93. packetOut.put("pic", pic);
  94.  
  95. consoleOut.printf("writeObject(input:%s)\n",cmd);
  96. socketOut.writeObject(packetOut);
  97. socketOut.flush();
  98.  
  99. consoleOut.printf("readObject()->output\n");
  100. packetIn = (Map<String, Object>) socketIn.readObject();
  101. output = (String) packetIn.get("output");
  102. output1 = (String) packetIn.get("output1");
  103. output2 = (String) packetIn.get("output2");
  104.  
  105. consoleOut.printf("output:%s\n",output);
  106. consoleOut.printf("output1:%s\n",output1);
  107. consoleOut.printf("output2:%s\n",output2);
  108. }
  109. }
  110. }
  1.  
  2. /*--------------------------------------------------
  3. $ java ServerMap4
  4. ListenTask: thread:pool-1-thread-1 (9) waiting at port:1234
  5. ServiceTask: thread: pool-1-thread-1 (9) serving /127.0.0.1:59626
  6. ServiceTask: socketOut
  7. ServiceTask: socketIn
  8. ServiceTask: end of constructor
  9. ListenTask: thread:pool-1-thread-1 (9) waiting at port:1234
  10. begin running
  11. waiting input
  12. cmd=<login1>
  13. parm1=<user>
  14. parm2=<passwd>
  15. parm=<[user, passwd]>
  16. vecResultSet=<[[user_id_1, passwod_1, email_1], [user_id_2, passwod_2, email_2]]>
  17. pic=width:728,height:90,write to 'test2.jpg'
  18. output=<LOGIN1>
  19. output1=<user>
  20. output2=<passwd>
  21. waiting input
  22. */
  23. import java.util.concurrent.*; // Executors
  24. import java.util.*; // 用到 Vector
  25. import java.net.*; // 用到 Socket, ServerSocket
  26. import java.io.*; // 用到 InputStream,InputStreamReader,BufferedReader
  27. // OutputStream,PrintWriter
  28. import javax.imageio.ImageIO;
  29. import javax.swing.ImageIcon;
  30. import java.awt.Image;
  31. import java.awt.image.BufferedImage;
  32. import java.awt.Graphics2D;
  33.  
  34. class ServiceTask implements Runnable
  35. {
  36. BufferedReader consoleIn; // 控制台輸入流
  37. PrintStream consoleOut; // 控制台輸出流
  38.  
  39. Socket skt;
  40. ObjectInputStream socketIn; // 連線插座輸入流
  41. ObjectOutputStream socketOut; // 連線插座輸出流
  42.  
  43. String host;
  44. String port;
  45.  
  46. public ServiceTask(Socket skt) throws IOException
  47. {
  48. // 取得螢幕輸出流
  49. consoleOut = System.err;
  50.  
  51. // 由連線插座,取得主機,埠號
  52. this.skt = skt;
  53. host = skt.getInetAddress().toString();
  54. port = String.valueOf(skt.getPort());
  55. consoleOut.printf("ServiceTask: thread: %s (%d) serving %s:%s\n",
  56. Thread.currentThread().getName(),
  57. Thread.currentThread().getId(), host,port);
  58.  
  59. // 由連線插座,取得插座輸出入資料流
  60. consoleOut.printf("ServiceTask: socketOut\n");
  61. OutputStream socketOs = skt.getOutputStream();
  62. socketOut = new ObjectOutputStream(socketOs);
  63.  
  64. consoleOut.printf("ServiceTask: socketIn\n");
  65. InputStream socketIs = skt.getInputStream();
  66. socketIn = new ObjectInputStream(socketIs);
  67.  
  68. consoleOut.printf("ServiceTask: end of constructor\n");
  69. }
  70.  
  71. @SuppressWarnings("unchecked")
  72. public void run()
  73. {
  74. consoleOut.printf("\tbegin running\n");
  75.  
  76. Map<String, Object> packetOut;
  77. Map<String, Object> packetIn;
  78.  
  79. // 測試字串陣列容器,結果集容器,圖片
  80. Vector<String> parm;
  81. Vector<Vector<String>> vecResultSet;
  82. ImageIcon pic;
  83.  
  84. try
  85. {
  86. // 進行多次對話,直到輸出為QUIT為止
  87. while(true)
  88. {
  89. consoleOut.printf("\twaiting input\n");
  90. packetIn = (Map<String, Object>) socketIn.readObject();
  91. String cmd = (String) packetIn.get("cmd");
  92. String parm1 = (String) packetIn.get("parm1");
  93. String parm2 = (String) packetIn.get("parm2");
  94. parm = (Vector<String>) packetIn.get("parm");
  95. vecResultSet = (Vector<Vector<String>>)packetIn.get("vecResultSet");
  96. pic = (ImageIcon) packetIn.get("pic");
  97.  
  98. consoleOut.printf("\tcmd=<%s>\n",cmd);
  99. consoleOut.printf("\tparm1=<%s>\n",parm1);
  100. consoleOut.printf("\tparm2=<%s>\n",parm2);
  101. consoleOut.printf("\tparm=<%s>\n",parm);
  102. consoleOut.printf("\tvecResultSet=<%s>\n",vecResultSet);
  103. consoleOut.printf("\tpic=width:%d,height:%d,write to '%s'\n",pic.getIconWidth(),pic.getIconHeight(),"test2.jpg");
  104.  
  105. // save image for comparison
  106. Image img = pic.getImage();
  107. BufferedImage bi = new BufferedImage(img.getWidth(null),img.getHeight(null),BufferedImage.TYPE_INT_RGB);
  108. Graphics2D g2 = bi.createGraphics();
  109. g2.drawImage(img, 0, 0, null);
  110. g2.dispose();
  111. ImageIO.write(bi, "jpg", new File("test2.jpg"));
  112.  
  113. String output = cmd.toUpperCase();
  114. String output1 = parm1;
  115. String output2 = parm2;
  116. packetOut = new HashMap<String, Object>();
  117. packetOut.put("output",output);
  118. packetOut.put("output1",output1);
  119. packetOut.put("output2",output2);
  120. socketOut.writeObject(packetOut);
  121. socketOut.flush();
  122. consoleOut.printf("\toutput=<%s>\n",output);
  123. consoleOut.printf("\toutput1=<%s>\n",output1);
  124. consoleOut.printf("\toutput2=<%s>\n",output2);
  125.  
  126. if(cmd.equals("quit")) break; // 遇到quit指令結束
  127. }
  128. }
  129. catch(Exception e)
  130. {
  131. consoleOut.printf("ServiceTask: exception:%s\n",e);
  132. }
  133. finally
  134. {
  135. // 關閉插座資料流和插座本身
  136. try
  137. {
  138. socketIn.close();
  139. socketOut.close();
  140. skt.close();
  141. }
  142. catch(IOException e)
  143. {
  144. consoleOut.printf("ServiceTask: socket close error:%s\n",e);
  145. }
  146. }
  147. }
  148. }
  149.  
  150. class ListenTask implements Runnable
  151. {
  152. int listenPort; // 監聽埠號
  153. ServerSocket listenSocket; // 監聽插座
  154. PrintStream consoleOut; // 控制台輸出流
  155.  
  156. ExecutorService pool; // 緒池
  157.  
  158. public ListenTask(ExecutorService pool, int port) throws IOException
  159. {
  160. this.listenPort = port;
  161. this.pool = pool;
  162.  
  163. consoleOut = System.err;
  164.  
  165. // 建立監聽插座,可能丟例外
  166. listenSocket = new ServerSocket(listenPort);
  167.  
  168. Runnable listenTask = this;
  169. Future f = pool.submit(listenTask);
  170. }
  171.  
  172. // 監聽緒工作
  173. public void run()
  174. {
  175. Socket connectedSocket=null;
  176.  
  177. try
  178. {
  179. while(true)
  180. {
  181. // 等待新連線
  182. consoleOut.printf("ListenTask: thread:%s (%d) waiting at port:%d\n",
  183. Thread.currentThread().getName(),
  184. Thread.currentThread().getId(),listenPort);
  185.  
  186. connectedSocket = listenSocket.accept();
  187.  
  188. // 啟動專屬緒,為新連線服務
  189. Runnable serviceTask = new ServiceTask(connectedSocket);
  190. pool.execute(serviceTask);
  191. }
  192. }
  193. catch(IOException e)
  194. {
  195. consoleOut.printf("ListenTask: accept raised IOException:%s\n",e);
  196. System.exit(0);
  197. }
  198. }
  199. }
  200.  
  201. public class ServerMap4
  202. {
  203. final int defaultPort = 1234;
  204. final ExecutorService pool;
  205.  
  206. public ServerMap4(int port)
  207. {
  208. pool = Executors.newCachedThreadPool(); // 建立緒池
  209. //pool = Executors.newFixedThreadPool(10);
  210.  
  211. try
  212. {
  213. if(port < 1024) port = defaultPort;
  214. ListenTask listenTask = new ListenTask(pool,port); // 開監聽緒
  215. }
  216. catch(IOException e)
  217. {
  218. System.err.printf("ServerMap4: %s\n", e);
  219. }
  220. }
  221.  
  222. public static void main(String args[]) throws Exception
  223. {
  224. int port = -1;
  225.  
  226. if(args.length==1) // 命令列有給埠號參數
  227. port = new Integer(args[0]).intValue(); // 則依命令列埠號
  228.  
  229. new ServerMap4(port); // 啟動監聽及服務緒
  230. }
  231. }

沒有留言: