您的位置:首页 > 其它

使用WebSocket实现多人实时聊天

2017-08-24 23:13 429 查看


一 应用

本应用使用WebSocket实现多人实时聊天

 

二 代码

客户端代码

Js代码  


<!DOCTYPE html>  
<html>  
<head>  
    <meta name="author" content="Yeeku.H.Lee(CrazyIt.org)" />  
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
    <title> 使用WebSocket通信 </title>  
    <script type="text/javascript">  
        // 创建Web Socket对象  
        var webSocket = new WebSocket("ws://127.0.0.1:30000");  
        webSocket.onopen = function()  
        {  
            // 为onmessage事件绑定监听器,接收消息  
            webSocket.onmessage= function(event)  
            {  
                // 接收、并显示消息  
                document.getElementById('show').innerHTML   
                    += event.data + "<br/>";  
            }  
        };  
        var sendMsg = function(val)  
        {  
            var inputElement = document.getElementById('msg');  
            // 发送消息  
            webSocket.send(inputElement.value);  
            // 清空单行文本框  
            inputElement.value = "";  
        }  
    </script>  
</head>  
<body>  
<div style="width:600px;height:240px;  
    overflow-y:auto;border:1px solid #333;" id="show"></div>  
<input type="text" size="80" id="msg" name="msg"/>  
<input type="button" value="发送" onclick="sendMsg();"/>  
</body>  
</html>  

 

服务器代码

Js代码  


import java.io.*;  
import java.net.*;  
import java.nio.charset.Charset;  
import java.security.MessageDigest;  
import java.util.regex.*;  
import java.util.*;  
import sun.misc.BASE64Encoder;  
/** 
 * Description: 
 * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a> 
 * <br/>Copyright (C), 2001-2012, Yeeku.H.Lee 
 * <br/>This program is protected by copyright laws. 
 * <br/>Program Name: 
 * <br/>Date: 
 * @author Yeeku.H.Lee kongyeeku@163.com 
 * @version 1.0 
 */  
public class ChatServer  
{  
    // 记录所有的客户端Soccket  
    public static List<Socket> clientSockets  
        = new ArrayList<Socket>();  
    public ChatServer()throws IOException  
    {  
        // 创建ServerSocket,准备接受客户端连接  
        ServerSocket ss = new ServerSocket(30000);  
        while(true)  
        {  
            // 接收到客户端连接  
            Socket socket = ss.accept();  
            // 将客户端Socket添加到clientSockets集合中  
            clientSockets.add(socket);  
            // 启动线程  
            new ServerThread(socket).start();  
        }  
    }  
    public static void main(String[] args)  
        throws Exception  
    {  
        new ChatServer();  
    }  
}  
class ServerThread extends Thread  
{  
    private Socket socket;  
    public ServerThread(Socket socket)  
    {  
        this.socket = socket;  
    }  
    public void run()  
    {  
        try  
        {  
            // 得到Socket对应的输入流  
            InputStream in = socket.getInputStream();  
            // 得到Socket对应的输出流  
            OutputStream out = socket.getOutputStream();  
            byte[] buff = new byte[1024];  
            String req = "";  
            // 读取数据,此时建立与WebSocket的"握手"。  
            int count = in.read(buff);  
            // 如果读取的数据长度大于0  
            if(count > 0)  
            {  
                // 将读取的数据转化为字符串  
                req = new String(buff , 0 , count);  
                System.out.println("握手请求:" + req);  
                // 获取WebSocket的key  
                String secKey = getSecWebSocketKey(req);  
                System.out.println("secKey = " + secKey);  
                String response = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: "  
                    + "websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "  
                        + getSecWebSocketAccept(secKey) + "\r\n\r\n";  
                System.out.println("secAccept = " + getSecWebSocketAccept(secKey));  
                out.write(response.getBytes());  
            }  
            int hasRead = 0;  
            // 不断读取WebSocket发送过来的数据  
            while((hasRead = in.read(buff)) > 0)  
            {  
                System.out.println("接收的字节数:" + hasRead);  
                /* 
                    因为WebSocket发送过来的数据遵循了一定的协议格式, 
                    其中第3个~第6个字节是数据掩码。 
                    从第7个字节开始才是真正的有效数据。 
                    因此程序使用第3个~第6个字节对后面的数据进行了处理 
                */  
                for (int i = 0 ; i < hasRead - 6 ; i++ )  
                {  
                    buff[i + 6] = (byte) (buff[i % 4 + 2] ^ buff[i + 6]);  
                }  
                // 获得从浏览器发送过来的数据  
                String pushMsg = new String(buff  
                    , 6 , hasRead - 6 , "UTF-8");  
                // 遍历Socket集合,依次向每个Socket发送数据  
                for (Iterator<Socket> it = ChatServer.clientSockets.iterator()  
                    ; it.hasNext() ;)  
                {  
                    try  
                    {  
                        Socket s = it.next();  
                        // 发送数据时,第一个字节必须与读到的第一个字节相同  
                        byte[] pushHead = new byte[2];  
                        pushHead[0] = buff[0];  
                        // 发送数据时,第二个字节记录发送数据的长度  
                        pushHead[1] = (byte) pushMsg.getBytes("UTF-8").length;  
                        // 发送前两个字节  
                        s.getOutputStream().write(pushHead);  
                        // 发送有效数据  
                        s.getOutputStream().write(pushMsg.getBytes("UTF-8"));  
                    }  
                    catch (SocketException ex)  
                    {  
                        // 如果捕捉到异常,表明该Socket已经关闭  
                        // 将该Socket从Socket集合中删除  
                        it.remove();  
                    }  
                }  
            }  
        }  
        catch (Exception e)  
        {  
            e.printStackTrace();  
        }  
        finally  
        {  
            try  
            {  
                // 关闭Socket  
                socket.close();  
            }  
            catch (IOException ex)  
            {  
                ex.printStackTrace();  
            }  
        }  
    }  
    // 获取WebSocket请求的SecKey  
    private String getSecWebSocketKey(String req)  
    {  
        //构建正则表达式,获取Sec-WebSocket-Key: 后面的内容  
        Pattern p = Pattern.compile("^(Sec-WebSocket-Key:).+",  
                Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);  
        Matcher m = p.matcher(req);  
        if (m.find())  
        {  
            // 提取Sec-WebSocket-Key  
            String foundstring = m.group();  
            return foundstring.split(":")[1].trim();  
        }  
        else  
        {  
            return null;  
        }  
    }  
    // 根据WebSocket请求的SecKey计算SecAccept  
    private String getSecWebSocketAccept(String key)  
        throws Exception  
    {  
        String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";  
        key += guid;  
        MessageDigest md = MessageDigest.getInstance("SHA-1");  
        md.update(key.getBytes("ISO-8859-1") , 0 , key.length());  
        byte[] sha1Hash = md.digest();  
        BASE64Encoder encoder = new BASE64Encoder();  
        return encoder.encode(sha1Hash);  
    }  
}  

 

 

三 运行结果



 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: