java學習小筆記(三.socket通信)

三,socket通信
1.http://blog.csdn.net/kongxx/article/details/7288896這個人寫的關於socket通信不錯,循序漸進式的講解,用代碼示例說明,運用流和socket進行遠程通訊

2.最簡單的socket是一個服務端對應一個客戶端
 server的寫法

  1. ServerSocket server = new ServerSocket(10000);  
  2.         Socket socket = server.accept();  
  3.         BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  4.         PrintWriter out = new PrintWriter(socket.getOutputStream());  
  5.           
  6.         while (true) {  
  7.             String msg = in.readLine();  
  8.             System.out.println(msg);  
  9.             out.println("Server received " + msg);  
  10.             out.flush();  
  11.             if (msg.equals("bye")) {  
  12.                 break;  
  13.             }  
  14.         }  
  15.         socket.close(); 
 
client的寫法
  1. Socket socket = new Socket("localhost"10000);  
  2.         BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  3.         PrintWriter out = new PrintWriter(socket.getOutputStream());  
  4.         BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));  
  5.   
  6.         while (true) {  
  7.             String msg = reader.readLine();  
  8.             out.println(msg);  
  9.             out.flush();  
  10.             if (msg.equals("bye")) {  
  11.                 break;  
  12.             }  
  13.             System.out.println(in.readLine());  
  14.         }  
  15.         socket.close(); 

3.複雜一點的就是多個客戶端同時訪問服務器。在客戶端使用循環啓動多個客戶端訪問同一服務端,在服務端只要server.accept()一接收到就新建線程,然後把把上面的讀寫操作放進線程內處理。

4.如果要利用socke傳遞對象,就要讓對象實現Serializable 序列化接口,使用ObjectInputStream和ObjectOutputStream進行序列化和反序列化
server的寫法
  1.  ObjectInputStream is = null;  
  2.                 ObjectOutputStream os = null;  
  3.                 try {  
  4.                     is = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));  
  5.                     os = new ObjectOutputStream(socket.getOutputStream());  
  6.   
  7.                     Object obj = is.readObject();  
  8.                     User user = (User)obj;  
  9.                     System.out.println("user: " + user.getName() + "/" + user.getPassword());  
  10.   
  11.                     user.setName(user.getName() + "_new");  
  12.                     user.setPassword(user.getPassword() + "_new");  
  13.   
  14.                     os.writeObject(user);  
  15.                     os.flush();  
  16.                 } catch (IOException ex) {  
client的寫法
  1. ObjectOutputStream os = null;  
  2.             ObjectInputStream is = null;  
  3.               
  4.             try {  
  5.                 socket = new Socket("localhost"10000);  
  6.       
  7.                 os = new ObjectOutputStream(socket.getOutputStream());  
  8.                 User user = new User("user_" + i, "password_" + i);  
  9.                 os.writeObject(user);  
  10.                 os.flush();  
  11.                   
  12.                 is = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));  
  13.                 Object obj = is.readObject();  
  14.                 if (obj != null) {  
  15.                     user = (User)obj;  
  16.                     System.out.println("user: " + user.getName() + "/" + user.getPassword());  
  17.                 }  
  18.             } catch(IOException ex) {  


5.如果還需要傳送時壓縮流再傳送,就要用到GZIPInputStream和GZIPOutputStream進行壓縮和反壓縮
server的寫法
  1. GZIPInputStream gzipis = null;  
  2.                 ObjectInputStream ois = null;  
  3.                 GZIPOutputStream gzipos = null;  
  4.                 ObjectOutputStream oos = null;  
  5.                   
  6.                 try {  
  7.                     gzipis = new GZIPInputStream(socket.getInputStream());  
  8.                     ois = new ObjectInputStream(gzipis);  
  9.                     gzipos = new GZIPOutputStream(socket.getOutputStream());  
  10.                     oos = new ObjectOutputStream(gzipos);  
  11.   
  12.                     Object obj = ois.readObject();  
  13.                     User user = (User)obj;  
  14.                     System.out.println("user: " + user.getName() + "/" + user.getPassword());  
  15.   
  16.                     user.setName(user.getName() + "_new");  
  17.                     user.setPassword(user.getPassword() + "_new");  
  18.   
  19.                     oos.writeObject(user);  
  20.                     oos.flush();  
  21.                     gzipos.finish();  
  22.                 } catch (IOException ex) {  
client的寫法
  1. Socket socket = null;  
  2.             GZIPOutputStream gzipos = null;  
  3.             ObjectOutputStream oos = null;  
  4.             GZIPInputStream gzipis = null;  
  5.             ObjectInputStream ois = null;  
  6.               
  7.             try {  
  8.                 socket = new Socket();  
  9.                 SocketAddress socketAddress = new InetSocketAddress("localhost"10000);   
  10.                 socket.connect(socketAddress, 10 * 1000);  
  11.                 socket.setSoTimeout(10 * 1000);  
  12.                   
  13.                 gzipos = new GZIPOutputStream(socket.getOutputStream());  
  14.                 oos = new ObjectOutputStream(gzipos);  
  15.                 User user = new User("user_" + i, "password_" + i);  
  16.                 oos.writeObject(user);  
  17.                 oos.flush();  
  18.                 gzipos.finish();  
  19.                   
  20.                 gzipis = new GZIPInputStream(socket.getInputStream());  
  21.                 ois = new ObjectInputStream(gzipis);  
  22.                 Object obj = ois.readObject();  
  23.                 if (obj != null) {  
  24.                     user = (User)obj;  
  25.                     System.out.println("user: " + user.getName() + "/" + user.getPassword());  
  26.                 }  
  27.             } catch(IOException ex) {  


6.如果要加密傳送,就要使用加密後的socket,而不是使用加密的流

server的寫法,只需要對socket進行處理,流的處理不變
  1. ServerSocketFactory factory = SSLServerSocketFactory.getDefault();  
  2.             ServerSocket server = factory.createServerSocket(10000);  

client的寫法
  1. SocketFactory factory = SSLSocketFactory.getDefault();  
  2.                 socket = factory.createSocket("localhost"10000);  
使用加密技術,需要用到keystore文件
keytool -genkey -alias mysocket -keyalg RSA -keystore mysocket.jks 

7.使用nio實現socket通信

java.nio包是Java在1.4之後增加的,用來提高I/O操作的效率。在nio包中主要包括以下幾個類或接口:

* Buffer:緩衝區,用來臨時存放輸入或輸出數據。

* Charset:用來把Unicode字符編碼和其它字符編碼互轉。

* Channel:數據傳輸通道,用來把Buffer中的數據寫入到數據源,或者把數據源中的數據讀入到Buffer。

* Selector:用來支持異步I/O操作,也叫非阻塞I/O操作。

把對象轉爲字節數組
  1. public static byte[] toBytes(Object object) {  
  2.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  3.         ObjectOutputStream oos = null;  
  4.         try {  
  5.             oos = new ObjectOutputStream(baos);  
  6.             oos.writeObject(object);  
  7.             byte[] bytes = baos.toByteArray();  
  8.             return bytes;  
吧字節數組轉爲對象
  1.  ByteArrayInputStream bais = new ByteArrayInputStream(bytes);  
  2.         ObjectInputStream ois = null;  
  3.         try {  
  4.             ois = new ObjectInputStream(bais);  
  5.             Object object = ois.readObject();  
  6.             return object; 
server端的寫法
  1. Selector selector = null;  
  2.         ServerSocketChannel serverSocketChannel = null;  
  3.         try { 
  4.             selector = Selector.open();
  5.             serverSocketChannel = ServerSocketChannel.open();  
  6.             serverSocketChannel.configureBlocking(false);  
  7.             serverSocketChannel.socket().setReuseAddress(true);  
  8.             serverSocketChannel.socket().bind(new InetSocketAddress(10000));  
  9.             serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);  
  10.             while (selector.select() > 0) {  
  11.                 Iterator<SelectionKey> it = selector.selectedKeys().iterator();   
  12.                 while (it.hasNext()) {  
  13.                     SelectionKey readyKey = it.next();  
  14.                     it.remove();  
  15.                     execute((ServerSocketChannel) readyKey.channel());  

    1. private static void execute(ServerSocketChannel serverSocketChannel) throws IOException {  
    2.         SocketChannel socketChannel = null;  
    3.         try {  
    4.             socketChannel = serverSocketChannel.accept();  
    5.             MyRequestObject myRequestObject = receiveData(socketChannel);  
    6.             logger.log(Level.INFO, myRequestObject.toString());  
    7.               
    8.             MyResponseObject myResponseObject = new MyResponseObject(  
    9.                     "response for " + myRequestObject.getName(),   
    10.                     "response for " + myRequestObject.getValue());  
    11.             sendData(socketChannel, myResponseObject);

    1.  MyRequestObject myRequestObject = null;  
    2.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
    3.         ByteBuffer buffer = ByteBuffer.allocate(1024);  
    4.           
    5.         try {  
    6.             byte[] bytes;  
    7.             int size = 0;  
    8.             while ((size = socketChannel.read(buffer)) >= 0) {  
    9.                 buffer.flip();  
    10.                 bytes = new byte[size];  
    11.                 buffer.get(bytes);  
    12.                 baos.write(bytes);  
    13.                 buffer.clear();  
    14.             }  
    15.             bytes = baos.toByteArray();  
    16.             Object obj = SerializableUtil.toObject(bytes);  
    17.             myRequestObject = (MyRequestObject)obj; 

    1.  sendData(SocketChannel socketChannel, MyResponseObject myResponseObject) throws IOException {  
    2.         byte[] bytes = SerializableUtil.toBytes(myResponseObject);  
    3.         ByteBuffer buffer = ByteBuffer.wrap(bytes);  
    4.         socketChannel.write(buffer);


client的寫法
  1. socketChannel = SocketChannel.open();  
  2.                 SocketAddress socketAddress = new InetSocketAddress("localhost"10000);  
  3.                 socketChannel.connect(socketAddress);  
  4.   
  5.                 MyRequestObject myRequestObject = new MyRequestObject("request_" + idx, "request_" + idx);  
  6.                 logger.log(Level.INFO, myRequestObject.toString());  
  7.                 sendData(socketChannel, myRequestObject);  
  8.                   
  9.                 MyResponseObject myResponseObject = receiveData(socketChannel);  
  10.                 logger.log(Level.INFO, myResponseObject.toString());  

  1.  private void sendData(SocketChannel socketChannel, MyRequestObject myRequestObject) throws IOException {  
  2.             byte[] bytes = SerializableUtil.toBytes(myRequestObject);  
  3.             ByteBuffer buffer = ByteBuffer.wrap(bytes);  
  4.             socketChannel.write(buffer);  
  5.             socketChannel.socket().shutdownOutput();

    1. private MyResponseObject receiveData(SocketChannel socketChannel) throws IOException {  
    2.             MyResponseObject myResponseObject = null;  
    3.             ByteArrayOutputStream baos = new ByteArrayOutputStream();  
    4.               
    5.             try {  
    6.                 ByteBuffer buffer = ByteBuffer.allocateDirect(1024);  
    7.                 byte[] bytes;  
    8.                 int count = 0;  
    9.                 while ((count = socketChannel.read(buffer)) >= 0) {  
    10.                     buffer.flip();  
    11.                     bytes = new byte[count];  
    12.                     buffer.get(bytes);  
    13.                     baos.write(bytes);  
    14.                     buffer.clear();  
    15.                 }  
    16.                 bytes = baos.toByteArray();  
    17.                 Object obj = SerializableUtil.toObject(bytes);  
    18.                 myResponseObject = (MyResponseObject) obj;  
    19.                 socketChannel.socket().shutdownInput(); 
    return myResponseObject;

上面的例子都需要先運行server再運行client。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章