一對一聊天ajax實現
前端頁面:
好友列表:
好友列表程式碼:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.Random" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>好友列表</title>
<script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="js/jquery.charfirst.pinyin.js"></script>
<script type="text/javascript" src="js/sort.js"></script>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/style1.css">
<style>
input {
border: 2px solid #7BA7AB;
border-radius: 5px;
}
</style>
<%
request.setCharacterEncoding("UTF-8");
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<base href="<%=basePath %>">
<script type="text/javascript">
$(function() {
timeID = setInterval('fresh()', 2000); //注意:執行的函式需要加引號,否則會報錯的
fresh();
});
function fresh(){
/*用這種方式重新整理的話效能太差*/
/* window.location.reload() */
var id = $("#username").val();
/* $.ajax({
data:id,
type:"post",
url:"friendList.action?username="+id,
dataType:"json",
success:function(){
},
error:function(){
}
}) */
}
function f(val){
$.ajax({
data : val,
type : "post",
url : "CharServlet?id=" + val,
dataType : "json",
success : function(msg) {
},
error : function(msg) {
alert("請求失敗");
}
});
}
</script>
</head>
<body>
<%
Random random = new Random();
request.setCharacterEncoding("UTF-8");
%>
<form id="fy" action="studentFind?" method="post">
<input id="find" name="find" onkeyup="f(this.value)"style="width:300px;height:20px; redius:1px;"type="text" placeholder="請輸入查詢的好友"/> <img id="searchImg"style="width:20px;"alt="" src="img/search.png">
<a href="javascript:window.location.href=''"></a>
<span id="mark"></span></a><a href="javascript:window.location.href='friend.jsp'"><img style="width:20px;"alt="" src="img/exit.png"></a>
</form>
<div class="gongneng">
<div class="page">
<img style="width:50px;height: 50px;" src="img/addFriend.svg" alt="">
</div>
<a href="commend.action?username=${user.username}">
新增好友
</a>
</div>
<div id="letter" ></div>
<div class="sort_box">
<c:forEach items="${list}" var="friend">
<div class="sort_list">
<div class="num_logo">
<!-- 輸出圖片 -->
<img src="img/<%=random.nextInt(7)+1%>.jpg" alt="">
</div>
<div class="num_name"><a href="sender2.jsp?name=${friend.name}&receiver=${friend.username}">${friend.name}</a></div>
</div>
</c:forEach>
</div>
<div class="initials">
<ul>
<li><img src="img/068.png"></li>
</ul>
</div>
<input type="hidden" id="username" value="${user.username}">
</body>
</html>
一對一聊天:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta charset="UTF-8">
<title>聊天助手</title>
<link rel="stylesheet" href="css/chat.css">
<link rel="alternate icon" href="assets/i/favicon.ico">
<link rel="stylesheet" href="assets/css/amazeui.min.css">
<link rel="stylesheet" href="assets/css/app.css">
<link href="umeditor/themes/default/css/umeditor.css" rel="stylesheet">
<link rel="stylesheet" href="css/chat.css">
<link rel="stylesheet" href="css/common.css" />
<link rel="stylesheet" href="css/layout.css" />
<link rel="stylesheet" href="css/app_bar.css" />
<link rel="stylesheet" href="css/header.css" />
<link rel="stylesheet" href="css/content.css" />
<script type="text/javascript" src="js/zs_me.js"></script>
<script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
.chat-content-container {
height: 49rem;
overflow-y: auto;
border: 1px solid silver;
}
.am-u-sm-6{
left:0px;
}
.am-u-sm-push-6{
width:100%;
}
</style>
<%
request.setCharacterEncoding("UTF-8");
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<base href="<%=basePath %>">
<script>
$(function() {
timeID = setInterval('f1()', 1000); //注意:執行的函式需要加引號,否則會報錯的
f1();
});
function f1(){
var username = $("#sender").val();
var friendid = $("#receiver").val();
var Rname=$('#name').val();
var Sname=$('#sendername').val();
$.ajax({
data:null,
type:"post",
url:"message.action?username="+encodeURIComponent(username)+"&friendid="+encodeURIComponent(friendid),
contentType: "application/json;charset=utf-8",
dataType:"json",
success:function(msg){
var num = $("#num").text();
var msNum = 0;
/*msNum資料庫中拿到的訊息數量*/
for(var i in msg){
msNum = msNum + 1;
}
if(msNum != num){
/*擷取訊息只保留新的訊息內容,存在的問題第一次載入不需要擷取*/
var len = 0;
$(msg).each(function(){
var cname;
/* len > num 說明資料庫訊息更新了 num==0 第一次載入訊息 */
if(len >= num || num==0){
if(this.sender == username){
isSelf = true;
cname=Sname;
}
else{
isSelf = false;
cname=Rname;
}
var messageItem = '<li class="am-comment '
+ (isSelf ? 'am-comment-flip' : 'am-comment')
+ '">'
+ '<a href="javascript:void(0)" ><img src="assets/images/'
+ (isSelf ? 'self.jpg' : 'others.jpg')
+ '" alt="" class="am-comment-avatar" width="48" height="48"/></a>'
+ '<div class="am-comment-main"><header class="am-comment-hd"><div class="am-comment-meta">'
+ '<a href="javascript:void(0)" class="am-comment-author">'
+ cname + '</a> <time>'
+ '</time></div></header>'
+ '<div class="am-comment-bd">' + this.message
+ '</div></div></li>';
$(messageItem).appendTo('#message-list');
// 把滾動條滾動到底部
$(".chat-content-container").scrollTop($(".chat-content-container")[0].scrollHeight);
}
len++;
});
/* num已接受的訊息數量 */
$("#num").html(msNum);
}
},
error:function(){
}
});
};
document.onkeydown = function(e) {
if (e.keyCode == 13 && e.ctrlKey) {
// 這裡實現換行
document.getElementById("sendContent").value += "\n";
} else if (e.keyCode == 13) {
// 避免Enter鍵換行
e.preventDefault();
// 下面寫你的傳送訊息的程式碼
f();
}
}
/*自定義時間格式*/
Date.prototype.Format = function (fmt) { // author: meizz
var o = {
"M+": this.getMonth() + 1, // 月份
"d+": this.getDate(), // 日
"h+": this.getHours(), // 小時
"m+": this.getMinutes(), // 分
"s+": this.getSeconds(), // 秒
"q+": Math.floor((this.getMonth() + 3) / 3), // 季度
"S": this.getMilliseconds() // 毫秒
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
function fc(){
window.location.href="friendList.action?username=${user.username}"
}
function f() {
/*得到訊息傳送時間*/
var time = new Date().Format("yyyy-MM-dd hh:mm:ss");
/* 獲得傳送的資訊 */
/* var goodslength = $(".").length; */
var cnt = $("#sendContent").val();
$('#sendContent').val('');
var sender = $("#sender").val();
var receiver = $("#receiver").val();
if(cnt == '')alert('內容不能為空');
if(cnt != ''){
/*訊息數量*/
var n = $("#num").text();
if(n>0){
$("#sendContent").val('');
}
$.ajax({
data : cnt,
type : "post",
url : "chat.action?content=" + encodeURIComponent(cnt)+"&sender="+sender+"&receiver="+receiver+"&time="+time,
contentType: "application/json;charset=utf-8",
dataType : "json",
success : function(msg) {
},
error : function(msg) {
}
});
}
}
</script>
</head>
<center>
<input id="sender" type="hidden" value="${user.username}"><br>
<input id="sendername" type="hidden" value="${user.name}"><br>
<!-- param接受a連結傳值 -->
<input id="receiver" type="hidden" value="${param.receiver}"><br>
<input id="name" type="hidden" value="${param.name}"><br>
<span style="visibility:hidden" id="num">0</span>
</center>
<!-- 聊天內容框開始 -->
<div class="am-container container" >
<div class="am-u-sm-12" style="background:#dcad50;">
<!-- <div class="am-u-sm-3 am-u-sm-push-6"> -->
<h3 style="text-align:center;margin-top:auto;margin-bottom:auto;padding:3px 0px;font-size:20px">${param.name}</h3>
<!-- </div> -->
</div>
<div class="chat-content-container">
<div class="am-u-sm-6 am-u-sm-push-6">
<ul id="message-list" class="am-comments-list am-comments-list-flip"></ul>
</div>
</div>
<!-- </div> -->
<!-- 聊天內容框結束 -->
<div class="message-input am-margin-top">
<!-- 輸入內容框開始 -->
</div>
<div class="border-img"></div>
<textarea id="sendContent" style="width:100%; height:19rem;"></textarea>
<!-- 輸入暱稱框開始 -->
<!-- <div class="am-g am-g-fixed am-margin-top"> -->
<div class="am-u-sm-6" style="display: none;">
<div id="message-input-nickname" class="am-input-group am-input-group-primary">
<span class="am-input-group-label"><i class="am-icon-user"></i></span>
<input id="nickname" type="text" class="am-form-field" value="${user.name}"/>
</div>
</div>
<div class="am-u-sm-12">
<p style="text-align:right;margin:0px">
<button onclick="fc()" class="am-btn am-btn-warning">
關閉
</button>
<button id="send" onclick="f()" type="button" class="send am-btn am-btn-primary">
<i class="am-icon-send"></i>傳送
</button>
</p>
</div>
</div>
</body>
</html>
後端處理:
package com.itcast.constroller;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.itcast.pojo.Chat;
import com.itcast.pojo.Commend;
import com.itcast.pojo.Commends;
import com.itcast.pojo.RegisterPojo;
import com.itcast.pojo.User;
import com.itcast.service.RegisterDemo;
import net.sf.json.JSONArray;
@Controller
public class ItemConstroller{
@Autowired
private RegisterDemo registerDemo;
@RequestMapping(value="/login.action")
/*登入驗證*/
public ModelAndView showLoginPage(String username, String password,HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model) throws IOException {
response.setCharacterEncoding("UTF-8");
User user = new User();
user.setUsername(username);
user.setPassword(password);
/*獲取使用者資訊*/
User myUser = registerDemo.queryByUser(user);
ModelAndView mv = new ModelAndView();
if(myUser!=null){
request.getSession().setAttribute("user", myUser);
mv.setViewName("friend.jsp");
}else{
mv.setViewName("login.jsp");
}
return mv;
}
/* public String showLoginPage(String username, String password,HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model) throws IOException {
User user = new User();
response.setCharacterEncoding("UTF-8");
user.setUsername(username);
user.setPassword(password);
User myUser = registerDemo.queryByUser(user);
if(myUser==null){
解決通過伺服器向頁面彈出對話方塊?
// PrintWriter out=response.getWriter();
// out.print("<script language=\"javascript\">alert('登入失敗!');window.location.href='/chat1/login.jsp'</script>");
return "redirect:/login.jsp";
}else{
return "redirect:/friend.html";
}
}*/
@RequestMapping(value="/test.action")
public void test(String id, HttpServletRequest request, HttpServletResponse response) throws IOException{
String str = request.getParameter(id);
System.out.println(str);
response.getWriter().write("{\"msg\":\"ok\"}");
}
/*驗證賬戶是否已經存在*/
@RequestMapping(value="/findUsername.action")
public void findUsername(String id,HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException{
System.out.println("驗證賬戶");
PrintWriter out = response.getWriter();
if(registerDemo.queryById(id) == null){
out.println("{\"state\":true }");
}else{
out.println("{\"state\":false }");
System.out.println("賬戶已經存在");
}
}
@RequestMapping(value="/register.action")
/*若要直接往response中寫內容而不經過檢視解析器時可以使用@ResponseBody
* @ResponseBody加上之後對返回ajax資料造成失效
* */
/*使用者註冊:RegisterPojo為註冊的資訊類*/
public void ItemUpdate(User user, HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException{
PrintWriter out = response.getWriter();
user.setGroupsum(3);
System.out.println(user.toString());
if(user.getCompany() == null && user.getEmail() == null && user.getPassword() == null && user.getSex() == null && user.getTel() == null && user.getUsername() == null){
out.println("{\"isSuccess\":false}");
}else{
if(registerDemo.insert(user)>0){
System.out.println("註冊成功");
out.println("{\"isSuccess\":true}");
}else{
System.out.println("註冊失敗");
out.println("{\"isSuccess\":false}");
}
}
}
@RequestMapping(value="/chat.action")
/*傳送訊息*/
public void AjaxSendMessage(String content, String sender, String receiver, String time, HttpServletRequest request, HttpServletResponse response){
Chat chat = new Chat();
System.out.println("內容"+content);
chat.setSender(sender);
StringBuilder str = new StringBuilder(content);
/*將時間拼接到訊息中 %作為識別符號*/
str.append("%").append(time);
content = str.toString();
chat.setMessage(content);
chat.setReceiver(receiver);
int insert = registerDemo.insert(chat);
if(insert > 0){
System.out.println("訊息儲存到資料庫中"+content);
}else{
System.out.println("訊息儲存失敗");
}
}
@RequestMapping(value="/message.action")
/*ajax接收訊息*/
public <T> void AjaxReceiveMessage(String username, String friendid, HttpServletRequest request, HttpServletResponse response) throws IOException{
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
//測試
// System.out.println("3333333333333333333"+username+"---"+friendid);
List<Chat> listSender = registerDemo.queryBySenderAndReceiver(username,friendid);
List<Chat> listReceiver = registerDemo.queryBySenderAndReceiver(friendid, username);
/*接受訊息按照時間進行排序並且區分傳送者和接受者 注意:當使用者傳送訊息的時候前端已經新增了div此時並不需要去重複新增工作*/
List<Chat> list = new ArrayList<>();
list = listSender;
list.addAll(listReceiver);
for (Chat chat : list) {
System.out.println("排序前:"+chat.getSender()+chat.getMessage()+chat.getReceiver());
}
/*時間排序*/
Collections.sort(list,new Comparator<Chat>() {
@Override
public int compare(Chat o1, Chat o2) {
//一開始沒設計好,按照時分秒儲存的訊息排序,隔天訊息亂序輸出
/* String[] split = o1.getMessage().split("%");
int len = split.length;
String time1 = split[len-1];
String[] tm = time1.split(":");
Integer[] a = new Integer[3];
a[0] = Integer.valueOf(tm[0]);
a[1] = Integer.valueOf(tm[1]);
a[2] = Integer.valueOf(tm[2]);
Time t1 = new Time(a[0], a[1], a[2]);
String[] split2 = o2.getMessage().split("%");
len = split2.length;
String time2 = split2[len-1];
String[] tm2 = time2.split(":");
Integer[] b = new Integer[3];
b[0] = Integer.valueOf(tm2[0]);
b[1] = Integer.valueOf(tm2[1]);
b[2] = Integer.valueOf(tm2[2]);
Time t2 = new Time(b[0],b[1],b[2]);
return t1.compareTo(t2);*/
//按照年月日時分秒儲存的訊息記錄排序
DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String[] split = o1.getMessage().split("%");
String[] split2 = o2.getMessage().split("%");
Date d1 = new Date();
Date d2 = new Date();
try {
d1 = format.parse(split[split.length-1]);
d2 = format.parse(split2[split2.length-1]);
} catch (ParseException e) {
e.printStackTrace();
}
return d1.compareTo(d2);
}
});
/*更改message擷取時間*/
for (int i = 0; i < list.size(); i++) {
Chat chat = list.get(i);
String[] s = chat.getMessage().split("%");
chat.setMessage(s[0]);
}
for (Chat chat : list) {
//System.out.println("排序後:"+chat.getSender()+chat.getMessage()+chat.getReceiver());
}
if(list.size()>0){
JSONArray json = JSONArray.fromObject(list);
//System.out.println("訊息:"+json);
out.println(json);
}else{
System.out.println("獲取資訊失敗");
}
}
/*獲取好友列表*/
@RequestMapping(value="/friendList.action")
public ModelAndView FriendList(String username, HttpServletRequest request, HttpServletResponse response){
List<String> list = registerDemo.queryFriendListById(username);
for (String s : list) {
System.out.println("好友id:"+s);
}
ModelAndView mv = new ModelAndView();
List<User> ll = new ArrayList<>();
if(list.size()>0){
for (String id : list) {
if(!id.equals("")){
User u = registerDemo.queryUserByid(id);
ll.add(u);
}
}
}else{
System.out.println("好友為空");
}
for (int i = 0; i < ll.size(); i++) {
if(ll.get(i).getUsername().equals(username)){
ll.remove(i);
}
}
request.setAttribute("list", ll);
// mv.addObject("list",list);
/*mv.setViewName("redirect:friendList.jsp");導致前端通過jstl無法獲取值問題?*/
mv.setViewName("friendList.jsp");
return mv;
}
/*查詢好友*/
@RequestMapping(value="/addFriend.action")
public <T> void addFriend(String username, HttpServletRequest request, HttpServletResponse response) throws IOException{
response.setContentType("text/html;charset=utf-8");
User user = registerDemo.queryById(username);
if(user!=null){
/*加入list集合才能轉換為jsonArray*/
List<User> list = new ArrayList<>();
list.add(user);
System.out.println("查詢的使用者資訊:"+user.getName()+user.getUsername());
PrintWriter out = response.getWriter();
JSONArray json = JSONArray.fromObject(list);
System.out.println(json);
out.println(json);
}else{
System.out.println("查詢的使用者不存在");
}
}
/*新增好友*/
@RequestMapping(value="/add.action")
public void add(String username, String id, HttpServletRequest request, HttpServletResponse response) throws IOException{
response.setContentType("text/html;charset=utf-8");
if("".equals(id)||"".equals(username))
return;
/*驗證是否已經新增過好友,避免重複新增操作*/
System.out.println("賬戶:"+username);
List<String> list = registerDemo.queryFriendListById(username);
PrintWriter out = response.getWriter();
boolean flag = true;
for (String string : list) {
if(string.equals(id)){
flag = false;
out.println(0);
}
}
if(flag){
out.println(1);
registerDemo.addFriendById(username,id);
registerDemo.addFriendById(id,username);
}
}
/*好友推薦*/
@RequestMapping(value="/commend.action")
public ModelAndView command(String username, HttpServletRequest request, HttpServletResponse response){
/*用來儲存關聯好友資訊*/
List<String> list = new ArrayList<>();
/*獲取當前使用者的好友*/
List<String> myFriend = registerDemo.queryFriendListById(username);
/*找出好友的好友*/
for (String id : myFriend) {
List<String> list2 = registerDemo.queryFriendListById(id);
list.addAll(list2);
}
System.out.println("我的好友"+myFriend);
/*推薦演算法實現*/
Set<String> set = new HashSet<>();
set.addAll(list);
Map<String,Integer> map = new HashMap<>();
for(String str : set){
map.put(str, 0);
}
for(String str : list){
Integer sum = map.get(str);
map.put(str, sum++);
}
List<Map.Entry<String, Integer>> listEntry = new ArrayList<>(map.entrySet());
Collections.sort(listEntry, new Comparator<Entry<String,Integer>>() {
@Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
List<Commend> l = new ArrayList<>();
myFriend.add(username);//把自己賬戶新增進去做去重操作
for (String ss : myFriend) {
System.out.println("我的朋友:"+ss);
}
boolean flag = true;
for (Entry<String, Integer> e : listEntry) {
for(String ch : myFriend){
if(ch.equals(e.getKey())){
flag = false;
}
}
if(flag){
l.add(new Commend(e.getKey(),e.getValue()));
}
flag = true;
}
/*去重操作,去掉已經新增完的好友*/
System.out.println("使用者"+username);
ModelAndView mv = new ModelAndView();
for (Commend commend : l) {
System.out.println("推薦好友123+:"+commend.getTimes()+commend.getUsername());
}
/*如果沒有好友推薦就推薦所有使用者*/
List<String> lUser = registerDemo.selectUser(username);
for (String s : lUser) {
l.add(new Commend(s, -1));
}
List<Commends> names = new ArrayList<>();
for (Commend c : l) {
User user = registerDemo.queryById(c.getUsername());
names.add(new Commends(c.getUsername(),c.getTimes(),user.getName()));
}
request.setAttribute("list", names);
/*mv.addObject("list",l);*/
mv.setViewName("searchFriend.jsp");
return mv;
}
}
用的springmvc框架,控制層處理獲取所有待處理的業務邏輯,持久化的操作用了mybatis,資料庫表的設計分為:好友列表表單和聊天資訊表單,其中欄位如圖:
加%號是為了和時間區分開,因為一開始資料庫未設計好在獲取聊天記錄的時候又需要按照時間進行排序,因為再新增欄位的話又需要在mapper中配置一些資訊,因此為了減少工作量直接在%後面追加內容用以區分。
聊天原理:因為http是無狀態的短連結,所以一次ajax請求結束後會自動斷開連結,因為如果想持續保持通訊的話必須新增一個定時器來定時通過ajax從伺服器取資料,達到通訊的目的,該方法的效能特別的差,不建議使用,因為之前並沒有學習websocket又想著用自己所學的知識來實現這通訊功能因為並沒有去考慮效能的問題,如果用websocket寫的話效能會更好,因為可以通過socket程式碼塊來操作傳輸層tcp的連線與斷開,因為tcp協議是長連線,它並不像應用層的http協議在處理一次請求之後就斷開並且所以的狀態資訊都被清空了,因為它也是無狀態的短連線,而相反使用tcp可以避免這個問題,如果如果websocket來實現一對一通訊的話,把使用者的id通過map進行儲存,這樣我們就可以通過key獲取value來達到一對一的通訊,而前面做的websocket的時候儲存使用者的時候是用set儲存然後再遍歷set集合讓各個客戶端都可以接受到聊天資訊。
相關文章
- Android:藍芽實現一對一聊天Android藍芽
- Laravel + swoole + redis 實現一對一聊天LaravelRedis
- 一對一聊天原始碼,vue實現環形進度條元件原始碼Vue元件
- 一對一聊天平臺原始碼,實現冪等的8種方案原始碼
- tp5+ajax+快取實現聊天室快取
- 如何基於 ZEGO SDK 實現 Android 一對一音視訊聊天應用GoAndroid
- 如何基於 ZEGO SDK 實現 Flutter 一對一音視訊聊天應用?GoFlutter
- 如何基於 ZEGO SDK 實現 Windows 一對一音視訊聊天應用GoWindows
- 實現一個webscoket聊天系統Web
- Ajax 實戰(一)
- Java聊天室——一對一模式Java模式
- 一對一聊天軟體原始碼,實現各個子介面跳轉和傳參原始碼
- MyBatis實現一對一關聯對映MyBatis
- node+socket.io 實現一個聊天室
- Andriod 實現一個類微信聊天介面 (二)
- Ajax 實現驗證郵箱地址唯一性
- Nodejs + WebSocket + Vue 一對一、一對多聊天室 - 第三章NodeJSWebVue
- 一對一直播交友帶社群匹配聊天一對多直播交友appAPP
- socket.io+express實現聊天室的思考(一)Express
- Android端實現多人音視訊聊天應用(一)Android
- 使用WebSocket實現一個簡單的頁面聊天Web
- 自己實現AJAX
- JavaScript Ajax 實現JavaScript
- 用node實現一個簡單的聊天室——websocket實踐Web
- Node+WebSocket+Vue 一對一、一對多聊天室訊息已讀未讀WebVue
- 基於Promise實現對Ajax的簡單封裝Promise封裝
- 如何實現一個前端對話前端
- ajax實現輪詢
- Netty網路聊天(一) 聊天室的實戰(最易懂)Netty
- 如何在零JS程式碼情況下實現一個實時聊天功能❓JS
- 用node實現一個簡單的聊天室—— 升級版
- 用Java程式碼實現一個簡單的聊天室功能Java
- 用Python實現一個人工智慧對對聯Python人工智慧
- Vue +WebSocket + WaveSurferJS 實現H5聊天對話互動VueWebJSH5
- TCP和UDP實現簡單一對一通訊TCPUDP
- 開發一對一直播聊天室一對一表演按分鐘賺錢的軟體系統。
- 巧妙利用 iframe,實現和 Ajax 一樣的非同步提交表單效果非同步
- #MyBatis多表查詢 #多對一、一對多的兩種實現方式 @FDDLCMyBatis