1. 程式人生 > >java websocket實現點對點即時聊天

java websocket實現點對點即時聊天

算是一個入門的demo,使用的是springMVC。

必要環境:JDK1.7以上,tomcat7.0以上。以下是乾貨:

1、websocket的jar直接從tomcat執行庫裡面新增到build path裡面。

2、前臺聊天頁面,通過ws://localhost:8080/newProject/websocketTest與後臺建立連線

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>

<title>My JSP 'socketChart.jsp' starting page</title>
<script type="text/javascript" src="js/jquery-1.8.2.js"></script>
</head>

<body>
	${username}<br/>
	線上人數:<div id="onlineCount">0</div>
	<br />
	傳送物件:<input id="username" type="text" width="50px"/>內容:<input id="text" type="text" />
	<button onclick="send()">傳送訊息</button>
	<hr />
	<button onclick="closeWebSocket()">關閉WebSocket連線</button>
	<hr />
	<div id="message"></div>
</body>
<script type="text/javascript">
	var websocket = null;
	//判斷當前瀏覽器是否支援WebSocket
	if ('WebSocket' in window) {
		websocket = new WebSocket("ws://localhost:8080/newProject/websocketTest");
	} else {
		alert('當前瀏覽器 Not support websocket')
	}
	//連線發生錯誤的回撥方法
	websocket.onerror = function() {
		setMessageInnerHTML("WebSocket連線發生錯誤");
	};
	//連線成功建立的回撥方法
	websocket.onopen = function() {
		setMessageInnerHTML("WebSocket連線成功");
	}
	//接收到訊息的回撥方法
	websocket.onmessage = function(event) {
		debugger
		var messageJson=eval("("+event.data+")");
		if(messageJson.messageType=="message"){
			setMessageInnerHTML(messageJson.data);
		}
		if(messageJson.messageType=="onlineCount"){
			document.getElementById('onlineCount').innerHTML=messageJson.data;
		}
		
	}
	//連線關閉的回撥方法
	websocket.onclose = function() {
		setMessageInnerHTML("WebSocket連線關閉");
	}
	//監聽視窗關閉事件,當視窗關閉時,主動去關閉websocket連線,防止連線還沒斷開就關閉視窗,server端會拋異常。
	window.onbeforeunload = function() {
		closeWebSocket();
	}
	//將訊息顯示在網頁上
	function setMessageInnerHTML(innerHTML) {
		document.getElementById('message').innerHTML += innerHTML + '<br/>';
	}
	//關閉WebSocket連線
	function closeWebSocket() {
		websocket.close();
	}
	//傳送訊息
	function send() {
		var message = document.getElementById('text').value;
		var username = document.getElementById('username').value;
		websocket.send(username+"@"+message);
		document.getElementById('message').innerHTML += message + '<br/>';
	}
</script>
</html>

3、登入頁面,簡單的建立一個session會話模擬使用者登入用作點對點聊天的唯一標識。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>My JSP 'login.jsp' starting page</title>

</head>

<body>
<center>
	<form action="chatWebsocket/login.do" method="post">
		<table>
			<tr>
				<td>username:</td><td><input type="text" id="username" name="username"/></td>
			</tr>
			<tr>
				<td colspan="2"> <input type="submit" value="登入"/></td>
			</tr>
		</table>
	</form>
</center>
</body>
</html>

4、controller類,模擬登入建立會話,並向socket工具類裡面傳送登入使用者的唯一標識。

package com.test.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.test.socket.WebSocketTest;

@Controller
@RequestMapping("chatWebsocket")
public class ChartWebsocketController {
	@RequestMapping("login")
	public void login(String username,HttpServletRequest request,HttpServletResponse response) throws Exception{
		HttpSession session=request.getSession();
		session.setAttribute("username", username);
		WebSocketTest.setHttpSession(session);
		request.getRequestDispatcher("/socketChart.jsp").forward(request, response);
	}
	@RequestMapping("loginOut")
	public void loginOut(HttpServletRequest request,HttpServletResponse response) throws Exception{
		HttpSession session=request.getSession();
		session.removeAttribute("username");
		request.getRequestDispatcher("/socketChart.jsp").forward(request, response);
	}
}

5、socket訊息處理類,負責訊息的接收與轉發,作用類似於TCP的服務端,@ServerEndpoint("/websocketTest")的作用是宣告websocket的連線路徑。

package com.test.socket;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpSession;
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;
import com.google.gson.Gson;

/**
 * @ServerEndpoint
 */
@ServerEndpoint("/websocketTest")
public class WebSocketTest {
	private static int onlineCount = 0;
	//存放所有登入使用者的Map集合,鍵:每個使用者的唯一標識(使用者名稱)
	private static Map<String,WebSocketTest> webSocketMap = new HashMap<String,WebSocketTest>();
	//session作為使用者簡歷連線的唯一會話,可以用來區別每個使用者
	private Session session;
	//httpsession用以在建立連線的時候獲取登入使用者的唯一標識(登入名),獲取到之後以鍵值對的方式存在Map物件裡面
	private static HttpSession httpSession;
	
	public static void setHttpSession(HttpSession httpSession){
		WebSocketTest.httpSession=httpSession;
	}
	/**
	 * 連線建立成功呼叫的方法
	 * @param session
	 * 可選的引數。session為與某個客戶端的連線會話,需要通過它來給客戶端傳送資料
	 */
	@OnOpen
	public void onOpen(Session session) {
		Gson gson=new Gson();
		this.session = session;
		webSocketMap.put((String) httpSession.getAttribute("username"), this);
		addOnlineCount(); // 
		MessageDto md=new MessageDto();
		md.setMessageType("onlineCount");
		md.setData(onlineCount+"");
		sendOnlineCount(gson.toJson(md));
		System.out.println(getOnlineCount());
	}
	/**
	 * 向所有線上使用者傳送線上人數
	 * @param message
	 */
	public void sendOnlineCount(String message){
		for (Entry<String,WebSocketTest> entry  : webSocketMap.entrySet()) {
			try {
				entry.getValue().sendMessage(message);
			} catch (IOException e) {
				continue;
			}
		}
	}
	
	/**
	 * 連線關閉呼叫的方法
	 */
	@OnClose
	public void onClose() {
		for (Entry<String,WebSocketTest> entry  : webSocketMap.entrySet()) {
			if(entry.getValue().session==this.session){
				webSocketMap.remove(entry.getKey());
				break;
			}
		}
		//webSocketMap.remove(httpSession.getAttribute("username"));
		subOnlineCount(); // 
		System.out.println(getOnlineCount());
	}

	/**
	 * 伺服器接收到客戶端訊息時呼叫的方法,(通過“@”擷取接收使用者的使用者名稱)
	 * 
	 * @param message
	 *            客戶端傳送過來的訊息
	 * @param session
	 *            資料來源客戶端的session
	 */
	@OnMessage
	public void onMessage(String message, Session session) {
		Gson gson=new Gson();
		System.out.println("收到客戶端的訊息:" + message);
		StringBuffer messageStr=new StringBuffer(message);
		if(messageStr.indexOf("@")!=-1){
			String targetname=messageStr.substring(0, messageStr.indexOf("@"));
			String sourcename="";
			for (Entry<String,WebSocketTest> entry  : webSocketMap.entrySet()) {
				//根據接收使用者名稱遍歷出接收物件
				if(targetname.equals(entry.getKey())){
					try {
						for (Entry<String,WebSocketTest> entry1  : webSocketMap.entrySet()) {
							//session在這裡作為客戶端向伺服器傳送資訊的會話,用來遍歷出資訊來源
							if(entry1.getValue().session==session){
								sourcename=entry1.getKey();
							}
						}
						MessageDto md=new MessageDto();
						md.setMessageType("message");
						md.setData(sourcename+":"+message.substring(messageStr.indexOf("@")+1));
						entry.getValue().sendMessage(gson.toJson(md));
					} catch (IOException e) {
						e.printStackTrace();
						continue;
					}
				}
				
			}
		}
		
	}

	/**
	 * 發生錯誤時呼叫
	 * 
	 * @param session
	 * @param error
	 */
	@OnError
	public void onError(Session session, Throwable error) {
		error.printStackTrace();
	}

	/**
	 * 這個方法與上面幾個方法不一樣。沒有用註解,是根據自己需要新增的方法。
	 * 
	 * @param message
	 * @throws IOException
	 */
	public void sendMessage(String message) throws IOException {
		this.session.getBasicRemote().sendText(message);
		// this.session.getAsyncRemote().sendText(message);
	}

	public static synchronized int getOnlineCount() {
		return onlineCount;
	}

	public static synchronized void addOnlineCount() {
		WebSocketTest.onlineCount++;
	}

	public static synchronized void subOnlineCount() {
		WebSocketTest.onlineCount--;
	}
}

6、訊息封裝的資料傳輸物件

package com.chart.dto;

public class MessageDto {
	private String messageType;
	private String data;
	public String getMessageType() {
		return messageType;
	}
	public void setMessageType(String messageType) {
		this.messageType = messageType;
	}
	public String getData() {
		return data;
	}
	public void setData(String data) {
		this.data = data;
	}
	
}

相關推薦

java websocket實現即時聊天

算是一個入門的demo,使用的是springMVC。 必要環境:JDK1.7以上,tomcat7.0以上。以下是乾貨: 1、websocket的jar直接從tomcat執行庫裡面新增到build path裡面。 2、前臺聊天頁面,通過ws://localhost:808

java WebSocket實現簡單的聊天室(包括群發和聊天

今天突然看到了WebSocket然後就網上找了一個例子,然後修改了下,實現了簡單的聊天室,包括群聊和點對點聊天。 使用的程式碼如下 jsp程式碼: <%@ page language="java" import="java.util.*" pageEncoding="

HTML5 WebSocket實現聊天的示例代碼

HTML案例分析 HTML5講解 HTML5的websocket與Tomcat實現了多人聊天,那是最簡單也是最基本的,其中註意的就是開發環境,要滿足jdk1.7和tomcat8,當然了tom7的7.063也行,在網站上找到了用google關於websocket的點對點聊天,更好的是可以和大多數系統很好

[NodeJS]NodeJS基於WebSocket的多用戶即時通訊聊天

round serve i++ conn console 即時通訊 .get () str 最近給一個客戶做了一個聊天,所以就用NodeJS做了一個 原理就是用戶第一次進入後,記錄它的ID和該用戶的ws 等有人發數據的時候,就去查ID,然後找到ID對應的ws,進行消息發

Spring Boot整合websocket實現群聊,聊天,圖片傳送,音訊傳送

參考:基於https://blog.csdn.net/qq_38455201/article/details/80374712  基礎上進行新增圖片傳送和音訊傳送功能   單點圖片傳送: 單點音訊傳送: 音訊傳送相關js參考:https://github.

java使用Netty實現聊天

最近學習伺服器開放,實現客戶端(APP)與硬體裝置之間的通訊,我一想到socket,經過查詢資料發現socket實現起來非常麻煩,同時也發現一個比較好的框架netty,覺得很不錯,就開始嘗試用他來擼一個點對點聊天系統,想了解的小夥伴可以自行去學習一下netty 一、一開始是導包,我是匯入

spring boot中使用websocket實現通訊與伺服器推送

WebSocket介紹    websocket是html中一種新的協議,它實現了真正的長連線,實現了瀏覽器與伺服器的全雙工通訊(指在通訊的任意時刻,線路上存在A到B和B到A的雙向訊號傳輸)。 現在我們接觸的協議大多是htttp協議,在瀏覽器中通過http協議實現了單向的通訊

nodejs 使用nodejs-websocket模組實現實時通訊

1、首先安裝好nodejs-websocket npm install nodejs-websocket --save -g 2、編寫服務端 var ws = require("nodejs-websocket") var AllUserData = new Array(

php從零搭建即時通訊(一.聊天)

目錄 零.在thinkphp5環境下搭建gatewayWork環境 2.下載完成後解壓到你TP5專案的vendor目錄下即可,如圖 3.點選start_for_win.bat檔案即可成功啟動你的webSocked伺服器,如果你是lin

SpringBoot整合WebSocket【基於STOMP協議】進行[一對一]和廣播[一對多]實時推送,內附簡易聊天室demo

最近專案來了新需求,需要做一個實時推送的功能,伺服器主動推送訊息給客戶端,在網上經過一輪搜查之後,確定使用WebSocket來進行開發。以前經常聽說WebSocket的神奇之處,如今終於可以嘗試使用它了。1.淺談WebSocketWebSocket是在HTML5基礎上單個TC

python實現簡單聊天應用(群聊和實現

後續程式碼更新和功能新增會提交到個人github主頁,有興趣可以一起來完善! 如果只是拿過去執行看結果,請注意平臺相關性以及python版本號,本示例開發執行平臺為win7x86_64 pycharm community,python版本號為3.5!!! T

聊天程式的實現

服務端 #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/

Spring boot:WebSocket+SockJS+Stomp實現廣播和訊息傳送

筆記 廣播式 STS工具新建spring boot專案 使用Thymeleaf和Websocket依賴 pom.xml: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave

java 實例

star bsp str ext div ase world 發送消息 ext.get 1.創建一個抽象類定義發送消息和接受消息的抽象方法 package cn.base.jms; import javax.jms.*; /** * @author

【181027】聊天室程式,,VC++程式原始碼

基於VC++的點對點聊天室程式,程式包括服務端和客戶端,伺服器程式是chatsrvr.exe,客戶端是ChatClient.exe.   伺服器先執行,客戶連線到伺服器執行的計算機的IP即可。在客戶端傳送訊息的時候,可選擇字型顏色、聊天物件、過濾、是否設定為悄悄話等,都是相對基礎點的功能,希望剛

SpringBoot+ActiveMq實現(Queue)訊息佇列

上篇博文主要分析了三種不同的請求方式,其中提到了基於訊息佇列的請求,當然只是從理論的角度去進行了分析,本篇博文就再次結合具體實現來說說訊息佇列。 一、什麼是訊息佇列? 作為中介軟體,訊息佇列是分散式應用間交換資訊的重要元件。訊息佇列可駐留在記憶體或磁碟上, 佇列可以儲存訊息直到它

Java程式碼實現遊戲24

最近正在練練編碼思維,程式碼如下 package cn.chetech.suanfa; import java.util.Scanner; /** * 24點遊戲是一個大眾化的益智遊戲。任意給4張撲克牌(不包括大小王),只能夠用加、減、乘、除以及適當的括號連線四張牌

基於TCP協議的通訊java程式,帶圖形介面

客戶端 package client; import java.awt.*; import java.awt.event.*; import java.io.DataInputStream; import java.io.DataOutputStream;

快速利用第三方平臺SDK,實現語音通話

最近公司的一個APP專案需要一個加一個網際網路點對點語音功能,網上找了Linphone 研究了一個月發現這些開源庫很強大也很優秀,支援平臺廣泛 windows, mac,ios,android,linux,但是程式碼量和結構實在龐大,坑爹的專案經理要求一個月把這個功

SpringBoot+WebSocket訊息通訊應用

1、在pom檔案中新增SpringSecurity依賴 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp