• 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。
  • 相关阅读:
    Vue Router路由组件传参
    Object.defineProperty()详解
    响应状态码
    ngnix端口转发
    查看端口占用情况
    nginx的查看、启动、停止、重载命令
    nginx的几个默认路径
    pm2的一些常用命令
    为什么要学习HTML?HTML会过时吗?
    48.MySQL数据库使用(二)
  • 原文地址:https://www.cnblogs.com/wxmdevelop/p/4238517.html
Copyright © 2020-2023  润新知