java Socket长链接与消息推送源码与演示
演示视频如下(在服务端输入消息,客户端接收消息) :
服务端代码 MyServer.java 源码如下
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 import java.io.OutputStream; 5 import java.io.PrintWriter; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 import java.util.HashMap; 9 import java.util.Iterator; 10 import java.util.Map; 11 import java.util.Scanner; 12 13 14 public class MyServer { 15 16 private static final Map<String,Socket> connectMap = new HashMap<String,Socket>(); //链接信息 17 18 private static ServerSocket server = null ; 19 20 private static final int PORT = 8888 ; 21 22 //SOCKET 服务线程类 23 static class ReciveService extends Thread{ 24 25 Socket client = null ; 26 27 private InputStreamReader is = null; 28 private BufferedReader in = null; 29 30 public ReciveService(Socket client){ 31 this.client = client ; 32 } 33 34 public void run() { 35 36 long tid =Thread.currentThread().getId() ;//当前线程ID 37 try{ 38 String IP = client.getInetAddress().getHostAddress() ; 39 40 System.out.println("已经链接 : "+IP+"["+tid+"]"); 41 connectMap.put(IP+"#"+tid,client); 42 is = new InputStreamReader(client.getInputStream(), "UTF-8");//规定编码 43 in = new BufferedReader(is);//接收请求的流 44 45 int len = 0;//监听到的字符串长度 46 char[] buf = new char[1024]; 47 while ((len = in.read(buf)) != -1) { 48 String s = new String(buf, 0, len); 49 s = new String(s.getBytes(),"utf-8"); 50 System.out.println("-> "+s); 51 } 52 }catch(Exception e){ 53 e.printStackTrace() ; 54 }finally{ 55 //关闭Socket 56 if(null != client){ 57 try { 58 client.close() ; 59 } catch (IOException e) { 60 e.printStackTrace(); 61 } 62 } 63 } 64 65 } 66 67 68 } 69 70 //向客户端发送消息 71 private static Thread tSend = new Thread(new Runnable(){ 72 Scanner scanner =new Scanner(System.in); 73 public void run() { 74 try { 75 while (true) { 76 String data = scanner.next() ; 77 for(Iterator<String> it = connectMap.keySet().iterator();it.hasNext();){ 78 String key = it.next() ;//IP+线程ID 79 Socket client = connectMap.get(key); 80 if(null != client && client.isConnected()){ 81 OutputStream os= client.getOutputStream(); 82 PrintWriter pw=new PrintWriter(os);//转化为打印流 83 pw.write(data); 84 pw.flush();//刷新缓存 85 } 86 } 87 Thread.sleep(1000); 88 // System.out.println("..."); 89 } 90 } catch (IOException e) { 91 e.printStackTrace(); 92 } catch (InterruptedException e) { 93 e.printStackTrace(); 94 } 95 } 96 }); 97 98 99 100 101 public static void main(String[] args) throws IOException { 102 System.out.println("==============SOCKET 服务端==============="); 103 startServer() ; 104 } 105 106 public static void startServer() throws IOException{ 107 server = new ServerSocket(PORT); 108 tSend.start(); //启动发送消息线程 109 while(true){ 110 try{ 111 Socket client = server.accept() ; //主线程获取客户端连接 112 ReciveService service = new ReciveService(client) ; 113 service.start(); //启动接收消息线程 114 }catch(Exception e){ 115 e.printStackTrace() ; 116 } 117 } 118 } 119 }
客户端代码 MyClient.java 源码如下 :
1 import java.io.IOException; 2 import java.io.InputStream; 3 import java.io.OutputStream; 4 import java.net.Socket; 5 import java.net.UnknownHostException; 6 import java.util.Scanner; 7 8 public class MyClient { 9 10 private static final ThreadLocal<Socket> threadConnect = new ThreadLocal<Socket>(); 11 12 private static final String HOST = "localhost"; 13 14 private static final int PORT = 8888; 15 16 private static Socket client; 17 18 private static OutputStream outStr = null; 19 20 private static InputStream inStr = null; 21 22 //数据接收线程 23 private static Thread tRecv = new Thread(new Runnable(){ 24 public void run() { 25 try { 26 // System.out.println("==============开始接收数据==============="); 27 while (true) { 28 byte[] b = new byte[1024]; 29 int r = inStr.read(b); 30 if(r>-1){ 31 String str = new String(b,0,r,"utf-8"); 32 System.out.println( str ); 33 } 34 } 35 } catch (IOException e) { 36 e.printStackTrace(); 37 } 38 } 39 }); 40 41 //消息发送线程 42 private static Thread tSend = new Thread(new Runnable(){ 43 Scanner scanner =new Scanner(System.in); 44 public void run() { 45 // System.out.println("=====================开始发送数据=============="); 46 try { 47 while (true) { 48 String data = scanner.next() ; 49 outStr.write(data.getBytes()); 50 } 51 } catch (IOException e) { 52 e.printStackTrace(); 53 } 54 } 55 56 }); 57 58 //心跳包发送线程 59 private static Thread tKeep = new Thread(new Runnable(){ 60 public void run() { 61 try { 62 // System.out.println("=====================开始发送心跳包=============="); 63 while (true) { 64 try { 65 //http://blog.csdn.net/qq_23167527/article/details/54290726 66 Thread.sleep(30000);//心跳频率 30秒 67 // System.out.println("."); 68 } catch (InterruptedException e) { 69 e.printStackTrace(); 70 } 71 //发送一个心跳数据包 72 outStr.write(new byte[]{});//发送非空包也可以 73 } 74 } catch (IOException e) { 75 e.printStackTrace(); 76 } 77 } 78 }); 79 80 /** 81 * @param args 82 */ 83 public static void main(String[] args) { 84 System.out.println("==============SOCKET 客户端==============="); 85 86 try { 87 connect(); 88 tRecv.start() ; 89 } catch (UnknownHostException e) { 90 e.printStackTrace(); 91 } catch (IOException e) { 92 e.printStackTrace(); 93 } 94 95 } 96 97 public static void connect() throws UnknownHostException, IOException { 98 client = threadConnect.get(); 99 if(client == null){ 100 client = new Socket(HOST, PORT); 101 threadConnect.set(client); 102 tKeep.start();//启动长连接心跳保活线程 103 tSend.start() ; 104 // System.out.println("========链接开始!========"); 105 } 106 outStr = client.getOutputStream(); 107 inStr = client.getInputStream(); 108 } 109 110 }