websocket實現用戶雙方通信
本文介紹一下websocket的用法,可能介紹的不夠專業,所有請見諒了。websocket可以是純Java實現,也可以整合Maven工程SSM框架實現,前端都是html或jsp的網頁進行websocket使用與實現。
我把兩種實現方法都說一下,但這兩種方法其實大概流程都一樣。
純Java的實現websocket
這是伺服器端的代碼:
package com.dlnu.man.util;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
/**
* @ServerEndpoint 註解是一個類層次的註解,它的功能主要是將目前的類定義成一個websocket伺服器端,
* 註解的值將被用於監聽用戶連接的終端訪問URL地址,客戶端可以通過這個URL來連接到WebSocket伺服器端
* @ServerEndpoint 可以把當前類變成websocket服務類
*/
@ServerEndpoint("/websocket/{userno}")
public class Socket {
//靜態變數,用來記錄當前在線連接數。應該把它設計成線程安全的。
private static int onlineCount = 0;
//concurrent包的線程安全Set,用來存放每個客戶端對應的MyWebSocket對象。若要實現服務端與單一客戶端通信的話,可以使用Map來存放,其中Key可以為用戶標識
private static ConcurrentHashMap<String, Socket> webSocketSet = new ConcurrentHashMap<String, Socket>();
//與某個客戶端的連接會話,需要通過它來給客戶端發送數據
private Session WebSocketsession;
//當前發消息的人員編號
private String userno = "";
/**
* 連接建立成功調用的方法
*
* @param session 可選的參數。session為與某個客戶端的連接會話,需要通過它來給客戶端發送數據
*/
@OnOpen
public void onOpen(@PathParam(value = "userno") String param, Session WebSocketsession, EndpointConfig config) {
System.out.println(param);
userno = param;//接收到發送消息的人員編號
this.WebSocketsession = WebSocketsession;
webSocketSet.put(param, this);//加入map中
addOnlineCount(); //在線數加1
System.out.println("有新連接加入!當前在線人數為" + getOnlineCount());
}
/**
* 連接關閉調用的方法
*/
@OnClose
public void onClose() {
if (!userno.equals("")) {
webSocketSet.remove(userno); //從set中刪除
subOnlineCount(); //在線數減1
System.out.println("有一連接關閉!當前在線人數為" + getOnlineCount());
}
}
/**
* 收到客戶端消息後調用的方法
*
* @param message 客戶端發送過來的消息
* @param session 可選的參數
*/
@SuppressWarnings("unused")
// @OnMessage
public void onMessage(String message, Session session) {
System.out.println("來自客戶端的消息:" + message);
// session.get
//群發消息
if (1 < 2) {
sendAll(message);
} else {
//給指定的人發消息
sendToUser(message);
}
}
/**
* 給指定的人發送消息
* @param message
*/
@OnMessage
public void sendToUser(String message) {
String sendUserno = message.split("[|]")[1];
String sendMessage = message.split("[|]")[0];
String now = getNowTime();
try {
if (webSocketSet.get(sendUserno) != null) {
webSocketSet.get(sendUserno).sendMessage(now + "用戶" + userno + "發來消息:" + " <br/> " + sendMessage);
} else {
System.out.println("當前用戶不在線");
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 給所有人發消息
* @param message
*/
private void sendAll(String message) {
String now = getNowTime();
String sendMessage = message.split("[|]")[0];
//遍歷HashMap
for (String key : webSocketSet.keySet()) {
try {
//判斷接收用戶是否是當前發消息的用戶
if (!userno.equals(key)) {
webSocketSet.get(key).sendMessage(now + "用戶" + userno + "發來消息:" + " <br/> " + sendMessage);
System.out.println("key = " + key);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 獲取當前時間
*
* @return
*/
private String getNowTime() {
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(date);
return time;
}
/**
* 發生錯誤時調用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("發生錯誤");
error.printStackTrace();
}
/**
* 這個方法與上面幾個方法不一樣。沒有用註解,是根據自己需要添加的方法。
*
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException {
this.WebSocketsession.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
Socket.onlineCount++;
}
public static synchronized void subOnlineCount() {
Socket.onlineCount--;
}
下面這是h5的代碼,用戶登錄,實現向資料庫傳遞參數,並返回相應的數據,成功後跳轉聊天界面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
//頁面載入完畢後執行,是$(document).ready(function(){});的簡寫
$(function(){
$("#login").click(function(){
var account=$("#account").val().trim();
var password=$("#pard").val().trim();
$.ajax({
url:"https://utils.top/Mens/Man/login",
type:"get",
dataType:"json",
data:{"account":account,"password":password},
success:function(result){
if(result.status==0){
window.location.href="soc1.jsp";
}else{
window.location.href="login2.html";
alert(result.msg);
}
},
error:function(){
alert("登錄異常");
}
});
});
});
</script>
</head>
<body>
<form action="login">
賬戶號:<input type="text" id="account"/>
密碼:<input type="password" id="pard"/>
<button id="login">登錄</button>
</form>
<br> <br> <br>
</body>
</html>
上面調用的是寫好的登錄介面,用的是Swagger工具進行調試API
登錄效果圖
下面是websocket的頁面及其代碼
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/popper.js/1.12.5/umd/popper.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/4.0.0-beta/js/bootstrap.min.js"></script>
<head>
<title>WebSocket的會話實現</title>
</head>
<body> <h2 stylex="text-align: center;">Welcome</h2>
<div stylex="margin-left: 7%;width: 50%;float: left;">
<br /> <br />
<input type="text" id="text" class="form-control" id="name" placeholder="發送消息內容">
<button type="button" class="btn btn-info" onclick="send()" stylex="float: right;;">發送消息</button>
<br /><hr>
<!--userno:發送消息人的編號-->
發送人:<div id="userno">${account}</div><br />
接收人: <input type="text" id="usernoto"
class="form-control" id="name" placeholder="接受者">
<br><br><br>
<button onclick="closeWebSocket()">關閉WebSocket連接</button>
<hr />
</div>
<div stylex="width: 40%;float: right;margin-top: 0%" id="message"></div>
</body>
<script type="text/javascript">
var websocket = null;
var userno=document.getElementById("userno").innerHTML;
//判斷當前瀏覽器是否支持WebSocket
if ("WebSocket" in window) {
websocket = new WebSocket("http://localhost:8080/sock/websocket/"+userno);
}
else {
alert("當前瀏覽器 Not support websocket")
}
//連接發生錯誤的回調方法
websocket.onerror = function () {
setMessageInnerHTML("WebSocket連接發生錯誤");
};
//連接成功建立的回調方法
websocket.onopen = function () {
setMessageInnerHTML("WebSocket連接成功");
}
//接收到消息的回調方法
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
}
//連接關閉的回調方法
websocket.onclose = function () {
setMessageInnerHTML("WebSocket連接關閉");
}
//監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。
window.onbeforeunload = function () {
closeWebSocket();
}
//將消息顯示在網頁上
function setMessageInnerHTML(sendMessage) {
document.getElementById("message").innerHTML += sendMessage + "<br/>";
}
//關閉WebSocket連接
function closeWebSocket() {
websocket.close();
}
//發送消息
function send() {
var message = document.getElementById("text").value;//要發送的消息內容
var now=getNowFormatDate();//獲取當前時間
document.getElementById("message").innerHTML += (now+"發送人:"+userno+"<br/>"+"---"+message) + "<br/>";
document.getElementById("message").style.color="red";
var ToSendUserno=document.getElementById("usernoto").value; //接收人編號:4567
message=message+"|"+ToSendUserno//將要發送的信息和內容拼起來,以便於服務端知道消息要發給誰
websocket.send(message);
}
//獲取當前時間
function getNowFormatDate() {
var date = new Date();
var seperator1 = "-";
var seperator2 = ":";
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate
+ " " + date.getHours() + seperator2 + date.getMinutes()
+ seperator2 + date.getSeconds();
return currentdate;
}
</script>
</html>
3702638926的會話頁面,其中的發送人賬號是登錄時產生session的值,
熊大的登錄和會話頁面
後台數據接收
連接成功以後,就可以輸入消息和對方的賬號,既可以進行相互間的消息傳遞
以上就是websocket的簡單功能實現!
第一次寫不夠標準,有部分也是參照網上學習的,所以部分會有重複的地方,諒解吧!
※JFinal框架學習——EhCachePlugin
※180918-JDK之Deflater壓縮與Inflater解壓
TAG:程序員小新人學習 |