java学习小笔记(三.socket通信)

来源:互联网 发布:java封装 编辑:程序博客网 时间:2024/05/17 03:59

三,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。
原创粉丝点击