2)对象消息
发送对象消息。服务端有LinkServer和LinkServer2两个,分别支持单客户端与多客户端,方式也有些不一样。
附件解压工程LinkedSocketB,.test包内Test开头的即是测试类了。服务端接收到客户端连接时,直接一个循环发送n个对象过去,没什么大问题^^。
2.1)LinkClient.java
- /**
- * 只建立一个Socket,长连接Server接收数据。
- *
- * @author Join
- */
- public class LinkClient extends Thread {
- /** 套接字地址 */
- private SocketAddress address;
- /** 超时时间 */
- private int timeout;
- /** 客户端监听接口 */
- private OnLinkClientListener listener;
- /**
- * 构造客户端
- *
- * @param host 服务器名称
- * @param port 服务器端口
- * @param timeout 连接超时时间
- */
- public LinkClient(String host, int port, int timeout) {
- this.address = new InetSocketAddress(host, port);
- this.timeout = timeout;
- }
- @Override
- public void run() {
- Socket socket = new Socket(); // 创建未连接套接字
- try {
- socket.connect(address, timeout); // 连接到服务器,并指定超时时间
- if (null != listener) {
- listener.onConnected();
- }
- receiveObj(socket); // 接收服务器数据
- } catch (ConnectException e) { // 拒绝连接
- if (null != listener) {
- listener.onConnectException();
- }
- } catch (SocketTimeoutException e) { // 连接超时
- if (null != listener) {
- listener.onTimeoutException();
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if (null != socket) {
- socket.close(); // 关闭Socket
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- /** 接收服务器发送的对象 */
- private void receiveObj(Socket socket) {
- // socket.shutdownOutput(); // 半关闭输出流
- ObjectInputStream is = null;
- try {
- is = new ObjectInputStream(new BufferedInputStream(
- socket.getInputStream()));
- /** 循环接收对象 */
- while (true) {
- Object obj = is.readObject();
- if (null == obj) {
- break;
- }
- if (null != listener) {
- listener.onReceive(obj);
- }
- }
- if (null != listener) {
- listener.onExited();
- }
- } catch (SocketException e) { // Connection reset
- if (null != listener) {
- listener.onSocketException();
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } finally {
- try {
- if (null != is) {
- is.close();
- }
- if (null != socket) {
- socket.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- /** 设置客户端监听接口 */
- public void setOnLinkClientListener(OnLinkClientListener listener) {
- this.listener = listener;
- }
- }
2.2)LinkServer.java
- /**
- * 开启服务器,长连接一个Socket,主动发送数据
- *
- * @author Join
- */
- public class LinkServer extends Thread {
- /** 服务端口 */
- private int port;
- /** 服务套接字 */
- private ServerSocket mServerSocket;
- /** 线程池 */
- private ExecutorService pool;
- /** 服务器监听接口 */
- private OnLinkServerListener listener;
- /** 同步对象 */
- private Object lockObj = new Object();
- /** 是否等待 */
- private boolean isWaiting = false;
- /** 发送对象集合 */
- private ArrayList<Object> sendObjList;
- public LinkServer(int port) {
- this.port = port;
- pool = Executors.newCachedThreadPool(); // 缓存线程池
- sendObjList = new ArrayList<Object>();
- }
- @Override
- public void run() {
- try {
- mServerSocket = new ServerSocket(port); // 创建本地特定端口服务器套接字
- Socket client = null;
- client = mServerSocket.accept(); // 接收连接的套接字
- if (null != listener) {
- listener.onClientConnected(client.getInetAddress());
- }
- pool.execute(new ThreadServer(client)); // 新线程执行任务
- } catch (BindException e) { // 端口使用中
- if (null != listener) {
- listener.onBindException();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /** 各个连接客户端的服务线程 */
- private class ThreadServer extends Thread {
- private Socket client;
- public ThreadServer(Socket client) {
- this.client = client;
- }
- @Override
- public void run() {
- ObjectOutputStream os = null;
- try {
- os = new ObjectOutputStream(client.getOutputStream());
- Object sendObj;
- synchronized (lockObj) {
- while (true) {
- if (sendObjList.size() <= 0) {
- isWaiting = true;
- lockObj.wait();
- }
- sendObj = sendObjList.get(0);
- os.writeObject(sendObj);
- os.flush();
- /* 发送null时,表示退出了 */
- if (null == sendObj) {
- if (null != listener) {
- listener.onExited(client.getInetAddress());
- }
- break;
- }
- sendObjList.remove(0);
- }
- }
- } catch (SocketException e) { // Connection reset
- if (null != listener) {
- listener.onSocketException(client.getInetAddress());
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally {
- try {
- if (null != os) {
- os.close();
- }
- if (null != client) {
- client.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- /** 发送序列化对象 */
- public void sendObj(Object obj) {
- /* 这个判断非必需的,记得就好 */
- if (null != obj && !isSerializable(obj))
- throw new IllegalArgumentException(
- "Object needs to implement java.io.Serializable!");
- sendObjList.add(obj);
- if (isWaiting) {
- synchronized (lockObj) {
- lockObj.notifyAll();
- }
- isWaiting = false;
- }
- }
- /** 判断是否序列化 */
- private boolean isSerializa
- ble(Object obj) {
- Class<?>[] cls = obj.getClass().getInterfaces();
- for (Class<?> clazz : cls) {
- if (clazz.getName().equals(Serializable.class.getName()))
- return true;
- }
- return false;
- }
- /** 设置服务器监听接口 */
- public void setOnLinkServerListener(OnLinkServerListener listener) {
- this.listener = listener;
- }
- }
本文转自winorlose2000 51CTO博客,原文链接:http://blog.51cto.com/vaero/893844,如需转载请自行联系原作者