使用WebSocket实现多人实时聊天


一 应用
本应用使用WebSocket实现多人实时聊天
 
二 代码
客户端代码
Js代码   收藏代码
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <meta name="author" content="Yeeku.H.Lee(CrazyIt.org)" />  
  5.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
  6.     <title> 使用WebSocket通信 </title>  
  7.     <script type="text/javascript">  
  8.         // 创建Web Socket对象  
  9.         var webSocket = new WebSocket("ws://127.0.0.1:30000");  
  10.         webSocket.onopen = function()  
  11.         {  
  12.             // 为onmessage事件绑定监听器,接收消息  
  13.             webSocket.onmessage= function(event)  
  14.             {  
  15.                 // 接收、并显示消息  
  16.                 document.getElementById('show').innerHTML   
  17.                     += event.data + "<br/>";  
  18.             }  
  19.         };  
  20.         var sendMsg = function(val)  
  21.         {  
  22.             var inputElement = document.getElementById('msg');  
  23.             // 发送消息  
  24.             webSocket.send(inputElement.value);  
  25.             // 清空单行文本框  
  26.             inputElement.value = "";  
  27.         }  
  28.     </script>  
  29. </head>  
  30. <body>  
  31. <div style="width:600px;height:240px;  
  32.     overflow-y:auto;border:1px solid #333;" id="show"></div>  
  33. <input type="text" size="80" id="msg" name="msg"/>  
  34. <input type="button" value="发送" οnclick="sendMsg();"/>  
  35. </body>  
  36. </html>  
 
服务器代码
Js代码   收藏代码
  1. import java.io.*;  
  2. import java.net.*;  
  3. import java.nio.charset.Charset;  
  4. import java.security.MessageDigest;  
  5. import java.util.regex.*;  
  6. import java.util.*;  
  7. import sun.misc.BASE64Encoder;  
  8. /** 
  9.  * Description: 
  10.  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a> 
  11.  * <br/>Copyright (C), 2001-2012, Yeeku.H.Lee 
  12.  * <br/>This program is protected by copyright laws. 
  13.  * <br/>Program Name: 
  14.  * <br/>Date: 
  15.  * @author Yeeku.H.Lee kongyeeku@163.com 
  16.  * @version 1.0 
  17.  */  
  18. public class ChatServer  
  19. {  
  20.     // 记录所有的客户端Soccket  
  21.     public static List<Socket> clientSockets  
  22.         = new ArrayList<Socket>();  
  23.     public ChatServer()throws IOException  
  24.     {  
  25.         // 创建ServerSocket,准备接受客户端连接  
  26.         ServerSocket ss = new ServerSocket(30000);  
  27.         while(true)  
  28.         {  
  29.             // 接收到客户端连接  
  30.             Socket socket = ss.accept();  
  31.             // 将客户端Socket添加到clientSockets集合中  
  32.             clientSockets.add(socket);  
  33.             // 启动线程  
  34.             new ServerThread(socket).start();  
  35.         }  
  36.     }  
  37.     public static void main(String[] args)  
  38.         throws Exception  
  39.     {  
  40.         new ChatServer();  
  41.     }  
  42. }  
  43. class ServerThread extends Thread  
  44. {  
  45.     private Socket socket;  
  46.     public ServerThread(Socket socket)  
  47.     {  
  48.         this.socket = socket;  
  49.     }  
  50.     public void run()  
  51.     {  
  52.         try  
  53.         {  
  54.             // 得到Socket对应的输入流  
  55.             InputStream in = socket.getInputStream();  
  56.             // 得到Socket对应的输出流  
  57.             OutputStream out = socket.getOutputStream();  
  58.             byte[] buff = new byte[1024];  
  59.             String req = "";  
  60.             // 读取数据,此时建立与WebSocket的"握手"。  
  61.             int count = in.read(buff);  
  62.             // 如果读取的数据长度大于0  
  63.             if(count > 0)  
  64.             {  
  65.                 // 将读取的数据转化为字符串  
  66.                 req = new String(buff , 0 , count);  
  67.                 System.out.println("握手请求:" + req);  
  68.                 // 获取WebSocket的key  
  69.                 String secKey = getSecWebSocketKey(req);  
  70.                 System.out.println("secKey = " + secKey);  
  71.                 String response = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: "  
  72.                     + "websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "  
  73.                         + getSecWebSocketAccept(secKey) + "\r\n\r\n";  
  74.                 System.out.println("secAccept = " + getSecWebSocketAccept(secKey));  
  75.                 out.write(response.getBytes());  
  76.             }  
  77.             int hasRead = 0;  
  78.             // 不断读取WebSocket发送过来的数据  
  79.             while((hasRead = in.read(buff)) > 0)  
  80.             {  
  81.                 System.out.println("接收的字节数:" + hasRead);  
  82.                 /* 
  83.                     因为WebSocket发送过来的数据遵循了一定的协议格式, 
  84.                     其中第3个~第6个字节是数据掩码。 
  85.                     从第7个字节开始才是真正的有效数据。 
  86.                     因此程序使用第3个~第6个字节对后面的数据进行了处理 
  87.                 */  
  88.                 for (int i = 0 ; i < hasRead - 6 ; i++ )  
  89.                 {  
  90.                     buff[i + 6] = (byte) (buff[i % 4 + 2] ^ buff[i + 6]);  
  91.                 }  
  92.                 // 获得从浏览器发送过来的数据  
  93.                 String pushMsg = new String(buff  
  94.                     , 6 , hasRead - 6 , "UTF-8");  
  95.                 // 遍历Socket集合,依次向每个Socket发送数据  
  96.                 for (Iterator<Socket> it = ChatServer.clientSockets.iterator()  
  97.                     ; it.hasNext() ;)  
  98.                 {  
  99.                     try  
  100.                     {  
  101.                         Socket s = it.next();  
  102.                         // 发送数据时,第一个字节必须与读到的第一个字节相同  
  103.                         byte[] pushHead = new byte[2];  
  104.                         pushHead[0] = buff[0];  
  105.                         // 发送数据时,第二个字节记录发送数据的长度  
  106.                         pushHead[1] = (byte) pushMsg.getBytes("UTF-8").length;  
  107.                         // 发送前两个字节  
  108.                         s.getOutputStream().write(pushHead);  
  109.                         // 发送有效数据  
  110.                         s.getOutputStream().write(pushMsg.getBytes("UTF-8"));  
  111.                     }  
  112.                     catch (SocketException ex)  
  113.                     {  
  114.                         // 如果捕捉到异常,表明该Socket已经关闭  
  115.                         // 将该Socket从Socket集合中删除  
  116.                         it.remove();  
  117.                     }  
  118.                 }  
  119.             }  
  120.         }  
  121.         catch (Exception e)  
  122.         {  
  123.             e.printStackTrace();  
  124.         }  
  125.         finally  
  126.         {  
  127.             try  
  128.             {  
  129.                 // 关闭Socket  
  130.                 socket.close();  
  131.             }  
  132.             catch (IOException ex)  
  133.             {  
  134.                 ex.printStackTrace();  
  135.             }  
  136.         }  
  137.     }  
  138.     // 获取WebSocket请求的SecKey  
  139.     private String getSecWebSocketKey(String req)  
  140.     {  
  141.         //构建正则表达式,获取Sec-WebSocket-Key: 后面的内容  
  142.         Pattern p = Pattern.compile("^(Sec-WebSocket-Key:).+",  
  143.                 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);  
  144.         Matcher m = p.matcher(req);  
  145.         if (m.find())  
  146.         {  
  147.             // 提取Sec-WebSocket-Key  
  148.             String foundstring = m.group();  
  149.             return foundstring.split(":")[1].trim();  
  150.         }  
  151.         else  
  152.         {  
  153.             return null;  
  154.         }  
  155.     }  
  156.     // 根据WebSocket请求的SecKey计算SecAccept  
  157.     private String getSecWebSocketAccept(String key)  
  158.         throws Exception  
  159.     {  
  160.         String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";  
  161.         key += guid;  
  162.         MessageDigest md = MessageDigest.getInstance("SHA-1");  
  163.         md.update(key.getBytes("ISO-8859-1") , 0 , key.length());  
  164.         byte[] sha1Hash = md.digest();  
  165.         BASE64Encoder encoder = new BASE64Encoder();  
  166.         return encoder.encode(sha1Hash);  
  167.     }  
  168. }  
 
 
三 运行结果

 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心歌技术

打赏不能超过你的早餐钱!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值