WebSocket介绍和一个简单的聊天室
WebSocket是什么呢?
WebSocket一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范,WebSocketAPI被W3C定为标准。
WebSocket 是独立的、创建在 TCP 上的协议,和 HTTP 的唯一关联是使用 HTTP 协议的101状态码进行协议切换,使用的 TCP 端口是80,可以用于绕过大多数防火墙的限制。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端直接向客户端推送数据而不需要客户端进行请求,在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并允许数据进行双向传送。
目前常见的浏览器如 Chrome、IE、Firefox、Safari、Opera 等都支持 WebSocket,同时需要服务端程序支持 WebSocket。
--------------------------------------------------------------------------------------
以上摘自wiki,总的来说websocket实现了服务器和浏览器之间的双向通信,摆脱了以往的一问一答的通信方式,可以自由地传输数据.
Websocket有什么优点?
- 由于没有http头信息,所以传输的数据包很小
- 服务器可以主动推送信息
Websocket的握手协议
还是照搬wiki上的例子,websocket在建立连接时,浏览器会向服务器发出如下请求
GET / HTTP/1.1 Upgrade: websocket Connection: Upgrade Host: example.com Origin: null Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ== Sec-WebSocket-Version: 13
这段请求会告诉服务器即将切换到websocket协议,如果服务器支持的话,会返回如下信息
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s= Sec-WebSocket-Origin: null Sec-WebSocket-Location: ws://example.com/
至此,握手阶段完成,服务器和浏览器之间可以开始发送和接收信息
使用Websocket实现一个简单的网页聊天室
- 使用tomcat8的websocket-api
- 参考tomcat自带的example
服务器端ChatServlet
package com.yc.chatroom;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.annotation.WebServlet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value="/websocket/chat")//指定客户端连接地址
public class ChatServlet {
private static final long serialVersionUID = 1L;
private static final String GUEST_PREFIX = "Guest";
private static final AtomicInteger connectionIds = new AtomicInteger(0);
private static final Set<ChatServlet> connections = new CopyOnWriteArraySet<ChatServlet>();
private final String nickname;
private Session session;
public ChatServlet() {
nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
}
@OnOpen
public void start(Session session) {
this.session = session;
connections.add(this);
String message = String.format("* %s %s", nickname, "has joined.");
broadcast(message); //广播用户加入消息
}
@OnClose
public void end() {
connections.remove(this);
String message = String.format("* %s %s", nickname, "has disconnected.");
broadcast(message); //广播用户推出消息
}
@OnMessage
public void incoming(String message) {
// Never trust the client
String filteredMessage = String.format("%s: %s", nickname, message.toString());
broadcast(filteredMessage); //广播发送内容
}
@OnError
public void onError(Throwable t) throws Throwable {
t.printStackTrace();
}
private static void broadcast(String msg) {
for (ChatServlet client : connections) {
try {
synchronized (client) {
client.session.getBasicRemote().sendText(msg);//给每个人发送消息
}
} catch (IOException e) {
connections.remove(client);
try {
client.session.close();
} catch (IOException e1) {
// Ignore
}
String message = String.format("* %s %s", client.nickname, "has been disconnected.");
broadcast(message);
}
}
}
}
浏览器端index.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<title>Apache Tomcat WebSocket Examples: Chat</title>
<style type="text/css">
input#chat {
width: 410px
}
#console-container {
width: 400px;
}
#console {
border: 1px solid #CCCCCC;
border-right-color: #999999;
border-bottom-color: #999999;
height: 170px;
overflow-y: scroll;
padding: 5px;
width: 100%;
}
#console p {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div>
<p>
<input type="text" placeholder="type and press enter to chat"
id="chat" />
</p>
<div id="console-container">
<div id="console"></div>
</div>
</div>
</body>
<script type="text/javascript">
/**
* 指定要连接的websocket地址
* 如果使用https,则使用wss://
**/
var socket = new WebSocket('ws://' + window.location.host+ '/chatroom/websocket/chat');
//连接与服务器的连接
socket.onopen = function() {
showMsg('Info: WebSocket connection opened.');
document.getElementById('chat').onkeydown = function(event) {
if (event.keyCode == 13) {
sendMsg();
}
};
};
//断开与服务器的连接
socket.onclose = function() {
document.getElementById('chat').onkeydown = null;
showMsg('Info: WebSocket closed.');
};
//与服务器之间的通信
socket.onmessage = function(message) {
showMsg(message.data);
};
//显示消息
function showMsg(message) {
var console = document.getElementById('console');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.innerHTML = message;
console.appendChild(p);
while (console.childNodes.length > 25) {
console.removeChild(console.firstChild);
}
console.scrollTop = console.scrollHeight;
}
//发送消息
function sendMsg() {
var message = document.getElementById('chat').value;
if (message != '') {
socket.send(message);
document.getElementById('chat').value = '';
}
}
</script>
运行结果
一次打开两个窗口,用户依次为guest0, guest1
guest0:

guest1:

guest0退出:

原文链接地址:https://mssora.com/websocket-intro-and-chatroom/
WebSocket介绍和一个简单的聊天室的更多相关文章
- 基于websocket实现的一个简单的聊天室
本文是基于websocket写的一个简单的聊天室的例子,可以实现简单的群聊和私聊.是基于websocket的注解方式编写的.(有一个小的缺陷,如果用户名是中文,会乱码,不知如何处理,如有人知道,请告知 ...
- [SignalR]一个简单的聊天室
原文:[SignalR]一个简单的聊天室 1.说明 开发环境:Microsoft Visual Studio 2010 以及需要安装NuGet. 2.添加SignalR所需要的类库以及脚本文件: 3. ...
- 用ServletContext做一个简单的聊天室
这里主要是ServletContext的一个特性:ServletContext是一个公共的空间,可以被所有的客户访问.由此可见ServletContext比cookie和session的作用范围要大[ ...
- ASP.NET Signalr 2.0 实现一个简单的聊天室
学习了一下SignalR 2.0,http://www.asp.net/signalr 文章写的很详细,如果头疼英文,还可以机翻成中文,虽然不是很准确,大概还是容易看明白. 理论要结合实践,自己动手做 ...
- 如何用WebSocket实现一个简单的聊天室以及单聊功能
百度百科中这样定义WebSocket:WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端.简单的说,We ...
- 通过WebSocket实现一个简单的聊天室功能
WebSocket WebSocket是一个协议,它是是基于TCP的一种新的网络协议,TCP协议是一种持续性的协议,和HTTP不同的是,它可以在服务器端主动向客户端推送消息.通过这个协议,可以在建立一 ...
- 使用ASP.NET SignalR实现一个简单的聊天室
前言 距离我写上一篇博客已经又过了一年半载了,时间过得很快,一眨眼,就把人变得沧桑了许多.青春是短暂的,知识是无限的.要用短暂的青春,去学无穷无尽的知识,及时当勉励,岁月不待人.今天写个随笔小结记录一 ...
- node实现一个简单的聊天室(认识一下socket)
边学边理解node的高深,今天写了一个聊天室的demo,很简单,认识一下socket node服务端代码 var express = require('express'); var app = exp ...
- 利用JavaUDPSocket+多线程模拟实现一个简单的聊天室程序
对Socket的一点个人理解:Socket原意是指插座.家家户户都有五花八门的家用电器,但它们共用统一制式的插座.这样做的好处就是将所有家用电器的通电方式统一化,不需要大费周章地在墙壁上凿洞并专门接电 ...
随机推荐
- mybatis 一对一与一对多collection和association的使用
在mybatis如何进行一对一.一对多的多表查询呢?这里用一个简单的例子说明. 一.一对一 1.association association通常用来映射一对一的关系,例如,有个类user,对应的实体 ...
- Oracle视图时间戳转为Date
CREATE OR REPLACE VIEW PDAORDER AS SELECT po.id id, po.order_no AS order_no, po.money AS money, (SEL ...
- 常用的js方法,包括表单校验的一些方法
/** * 对JSON对象转换为字符串. * @param {json对象} json * @return {json字符串} */ function jsonObj2Str(json) { var ...
- oracle--子查询--bai
-- 1 创建视图 show_max_sal_name_view 显示工资最高的员工姓名及他的工资 create or replace view show_max_sal_name_view as s ...
- ubuntu16.04文件形式安装mongodb
下载文件:mongodb-linux-x86_64-ubuntu1604-3.4.1.tgz,解压到home目录. 在mongodb目录下新建data/db目录. 在桌面新建一个shell文件run- ...
- Python Day21
Cookie 1.获取Cookie: request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt=' ...
- ubuntu下gedit闪退,遇到问题:ERROR:../../gi/pygi-argument.c:1583:_pygi_argument_to_object: code should not be reached 已放弃 (核心已转储)
解决方法:编辑->首选项关闭->插件->取消"多文件编辑"
- Java集合之HashMap
1. HashMap概述: HashMap是基于哈希表的Map接口的非同步实现(Hashtable跟HashMap很像,唯一的区别是Hashtalbe中的方法是线程安全的,也就是同步的).此实现提供所 ...
- ubuntu mysql使用
用navicat远程连不上mysql,提示10061错误解决办法: 修改/etc/mysql/my.cnf文件,找到127.0.0.1行,注释该行 命令:vi my.cnf 按i键进入编辑模式 编辑完 ...
- 阿里笔试题:在n个人中找明星
题目描述:有N个人,其中一个明星和n-1个群众,群众都认识明星,明星不认识任何群众,群众和群众之间的认识关系不知道,现在如果你是机器人R2T2,你每次问一个人是否认识另外一个人的代价为O(1),试设计 ...