最近从一篇博客中看到了Socket的介绍,是阿蜜果姐姐的博文:http://www.blogjava.net/amigoxie/archive/2007/02/11/99331.html,学习了下。
其实之前一直没有接触过Socket这方面的东西,工作中也没有用到,不过Socket是蛮重要的一个模块还是要研究下。
根据阿蜜果的文章,拿下来修改了一下,发现很好用,修改了一下就是一个可以交互对话的程序了
package com.socket; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * Socket的Server举例 * * @author Jason * @since 2013/08/11 */ public class SocketServer { ServerSocket serverSocket = null; Socket socket = null; DataInputStream inStream = null; DataOutputStream outStream = null; public static void main(String[] args) { SocketServer socketServer = new SocketServer(); socketServer.waitForClient(); } public SocketServer() { try { serverSocket = new ServerSocket(6600); } catch (Exception e) { e.printStackTrace(); } } void waitForClient() { try { socket = serverSocket.accept(); inStream = new DataInputStream(socket.getInputStream()); outStream = new DataOutputStream(socket.getOutputStream()); outStream.writeUTF("let's start our chart!"); socket.setSoTimeout(60000); acceptAndSendData(); } catch (Exception e) { e.printStackTrace(); } } void acceptAndSendData() { while (true) { try { String acceptStr = inStream.readUTF(); System.out.println("Server accept:" + acceptStr); if (acceptStr.toLowerCase().contains("end")) break; System.out.println("I:"); BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); String sendStr = br.readLine(); if (sendStr.toLowerCase().contains("end")) break; outStream.writeUTF(sendStr); } catch (Exception e) { e.printStackTrace(); break; } } } }
下面是Client的代码
package com.socket; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.net.Socket; /** * Socket的Client举例 * * @author Jason * @since 2013/08/11 */ public class SocketCliet { Socket socket = null; DataInputStream inStream = null; DataOutputStream outStream = null; public static void main(String[] args) { SocketCliet socketCliet = new SocketCliet(); } public SocketCliet() { try { init(); waitData(); } catch (Exception e) { e.printStackTrace(); } } void init() throws Exception { socket = new Socket("127.0.0.1", 6600); inStream = new DataInputStream(socket.getInputStream()); outStream = new DataOutputStream(socket.getOutputStream()); socket.setSoTimeout(60000); } void waitData() { boolean flag = true; while (flag) { try { String acceptStr = inStream.readUTF(); System.out.println("Client accept: " + acceptStr); if (acceptStr.toLowerCase().contains("end")) { System.out.println("End!"); break; } System.out.println("I:"); BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); String sendStr = br.readLine(); outStream.writeUTF(sendStr); if (sendStr.toLowerCase().contains("end")) break; } catch (Exception e) { e.printStackTrace(); break; } } } }
先启动Server,再启动Client程序。Server会先发送“let's start our chart!”给Client,然后Client会将输入的聊天语句发送给Server,Server和Client就建立了一个简单的可以输入文字,看见对方的回应的聊天程序。
其中有需要注意的几点:1,socket.setSoTimeout(60000);这个时间是连接的超时时间,如果超过60秒还没有交互的话,连接就会被丢弃。
2,程序设定了,任何一方输入end之后就会中断连接。这个过程程序一定要控制是服务器端先告诉客户端我要中断,然后关掉连接;客户端接受到关闭的指示后再去关闭连接,否则就会出错,抛出Connect Reset的异常。
这个程序还可以改造,任何一个聊天的程序都不会是客户端去跟服务器聊天,一定是两个或者更多的客户端之间的交互,服务器应该是作为一个中间者。可以考虑在每一个连接建立的时候分配一个空间作为聊天的平台。
例如,A告诉服务器我要建立一个聊天的平台叫做ABLove,然后服务器端建立一个Map存起来,key就是ABLove;B向服务器发起一个连接,说我要进入ABLove的平台;
A说一句I love you!,服务器把这句话放进Map的存储中,B连接的服务器捕捉到Map里的值有变化,就把这句话发送给B,B说I love you too!,同样的方式将会转给A。
当然Map只是一种假定,完全可以用另外的数据结构设计来存储这些东西去实现。