/** * 主程序启动入口 * * @param args */ public static void main(String[] args) { ctx = new ClassPathXmlApplicationContext(APPLICATION_XML_FILE); ctx.start(); // SingletonMessagePush instance=SingletonMessagePush.getInstance();//单例服务类 try { ServerSocket serverSocket=new ServerSocket(getMessagePushPort());//serverSocket,只负责监听客户端连接,一旦连接成功,服务端会新建一个socket负责与客户端通信 while(true){//不断监听客户端连接 Socket socket = serverSocket.accept();//返回一个客户端的Socket对象实例 // System.out.println("【发现客户端连接>>>>>>】"); if(null!=socket){ CopyOnWriteArrayList<Socket> oldList=instance.getSocket(); for (Socket so : oldList) { if(so.isConnected()==false||so.isClosed()==true){ instance.getSocket().remove(so);//移除 System.out.println(so.getInetAddress()+"从socket客户端集合移除。"); } } if(socket.isConnected()==true&&socket.isClosed()==false){ instance.getSocket().add(socket);//添加客户端socket System.out.println("添加客户端:"+socket.getInetAddress()+",当前有效客户端总数:"+instance.getSocket().size()); } } } } catch (Exception e) { e.printStackTrace(); System.out.println("主程序启动时服务端socket异常"); } }
2、推送消息单例类
package com.vxichina.cluster.persistence.core; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.Socket; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author mingfeng.wang * @date 2016年3月15日 * @time 上午10:54:18 * 向录屏程序推送消息的类 */ public class SingletonMessagePush { //有效客户端socket连接集合 private CopyOnWriteArrayList<Socket> socket=new CopyOnWriteArrayList<Socket>(); //线程池 private ExecutorService threadPool=Executors.newCachedThreadPool(); //private构造函数 private SingletonMessagePush(){ } private static SingletonMessagePush instance; //对外访问方法 public static SingletonMessagePush getInstance(){ if(null==instance){ instance=new SingletonMessagePush(); } return instance; } /** * 推送消息的主方法 * @param dataStr */ public void doMain(String dataStr){ try { if(null!=dataStr&&!"".equals(dataStr)){ if(null!=socket&&socket.size()>0){ //#s 给所有有效连接的客户端推送消息 for (Socket sc : this.getSocket()) { final String message=dataStr; final Socket clientSocket=sc; if(sc.isConnected()==true&&sc.isClosed()==false){ //new Thread(new Task(sc,dataStr)).start();//多线程 Thread.sleep(0); //线程池方式 threadPool.execute(new Runnable() { @Override public void run() { try { System.out.println("当前线程name="+Thread.currentThread().getName()+", id="+Thread.currentThread().getId()); // 服务端写数据 Writer writer = new OutputStreamWriter(clientSocket.getOutputStream()); writer.write(message); writer.flush(); System.out.println("成功给客户端"+clientSocket.getInetAddress()+"推送消息。消息内容:\n"+message); //writer.close();//不能关闭,关闭会导致客户端close一段时间 }catch (Exception e) { System.out.println("给客户端"+clientSocket.getInetAddress()+"推送消息异常。"); } } }); } } //#e }else{ System.out.println("暂无客户端连接。"); } } } catch (Exception e) { e.printStackTrace(); System.out.println("doMain推送消息异常。"); } } public CopyOnWriteArrayList<Socket> getSocket() { return socket; } public void setSocket(CopyOnWriteArrayList<Socket> socket) { this.socket = socket; } }
3、模拟客户端访问
public class ClientSocketTest { public static void main(String[] args) { String host="192.68.19.64";//自定义 int port=9080; try { Socket client = new Socket(host, port); while(true){ System.out.println("【>>>>>>客户端正在监听>>>>>>】,isConnected="+client.isConnected()+",isClosed="+client.isClosed()); // 客户端读数据 Reader reader = new InputStreamReader(client.getInputStream()); char chars[] = new char[64]; int len; StringBuffer sb = new StringBuffer(); while ((len = reader.read(chars)) != -1) { sb.append(new String(chars, 0, len)); } System.out.println("客户端读数据结束。" ); reader.close(); //client.close(); } }catch(java.net.SocketException e){ if(e.getMessage().equals("Connection reset")){ System.out.println("连接被重置,服务端已关闭。"); } }catch (Exception e) { e.printStackTrace(); System.out.println("客户端其它异常。"); } } }
===============================================================================
1、服务端监听端口
private static final String appConfigFile = "/app-config.properties"; public static void main(String[] args) { SingletonServerSocket singletonServerSocket=SingletonServerSocket.getInstance(); try { //System.out.println("端口:"+getMessagePushPort()); ServerSocket serverSocket=new ServerSocket(getMessagePushPort()); singletonServerSocket.setServerSocket(serverSocket);//serverSocket while(true){ Socket socket = serverSocket.accept();//监听,接受客户端连接 if(null!=socket){ singletonServerSocket.setSocket(socket); } } } catch (IOException e) { e.printStackTrace(); } } /** * 从Properties文件中获取推送信息需要监听的socket通信端口 * @return */ public static int getMessagePushPort(){ int port=0; Properties properties = new Properties(); try { properties.load(Object.class.getResourceAsStream(appConfigFile)); } catch (IOException e) { e.printStackTrace(); } port=Integer.valueOf(properties.getProperty("messagePushPort").trim()); return port; }
2、调用
SingletonServerSocket singletonServerSocket=SingletonServerSocket.getInstance();//单例类 //推送socket消息到客户端 singletonServerSocket.doMain(str.toString());
3、SingletonServerSocket 单例类-服务端写数据
public class SingletonServerSocket { private ServerSocket serverSocket; private Socket socket; //private构造函数 private SingletonServerSocket(){ } private static SingletonServerSocket instance; //对外访问方法 public static SingletonServerSocket getInstance(){ if(null==instance){ instance=new SingletonServerSocket(); } return instance; } /** * 推送消息的主方法 * @param dataStr */ public void doMain(String dataStr){ try { if(null!=dataStr&&!"".equals(dataStr)){ if(null!=socket){ new Thread(new Task(socket,dataStr)).start();//多线程 }else{ System.out.println("暂无客户端连接,无法完成写操作。"); } } } catch (Exception e) { e.printStackTrace(); } } /** * 用来处理socket请求的多线程 * * */ static class Task implements Runnable { private Socket socket2; private String data; public Task(Socket socket, String data) { this.socket2 = socket; this.data = data; } public void run() { try { handleSocket();// 处理客户端socket } catch (Exception e) { e.printStackTrace(); } } /** * 跟客户端Socket进行通信 * */ private void handleSocket(){ try { // 服务端写数据 Writer writer = new OutputStreamWriter(socket2.getOutputStream()); writer.write(data); System.out.println("服务端写数据:" + data); writer.flush(); //writer.close(); } catch (java.net.SocketException e) { System.out.println("无法找到写数据的客户端!"); } catch (Exception e) { System.out.println("服务端写数据错误!"); } // socket2.close();//服务端socket,不能关闭 } } public ServerSocket getServerSocket() { return serverSocket; } public void setServerSocket(ServerSocket serverSocket) { this.serverSocket = serverSocket; } public Socket getSocket() { return socket; } public void setSocket(Socket socket) { this.socket = socket; } }
4、客户端读数据
public class ClientSocket { public static void main(String[] args) { String host="192........"; int port=9099; try { Socket client = new Socket(host, port); while(true){ System.out.println("client request..."); if(client.isClosed()){ client = new Socket(host, port); } // 客户端读数据 Reader reader = new InputStreamReader(client.getInputStream()); char chars[] = new char[64]; int len; StringBuffer sb = new StringBuffer(); while ((len = reader.read(chars)) != -1) { sb.append(new String(chars, 0, len)); } System.out.println("客户端读数据:" + sb); reader.close(); client.close(); } } catch (Exception e) { e.printStackTrace(); } } }