网上聊天室开发思路

tech2024-12-12  6

网上聊天室设计思路

平时经常性的使用聊天软件如QQ,微信,或是游戏里各个区的公共频道,于是突发奇想,想要自己搞一个简易版聊天项目,所以现在开搞起来。


需求分析

1.想要进行聊天,势必需要有人才能聊起来,因此需要用户,且用户可以注册,登录(注册用户,打开主页,看到登录页面) 2.登录成功之后,就可以进入主页面 3.主页面显示现在用户关注的频道列表,即关注之后,才可以在此频道发言。 4.点击其中一个频道之后,就可以在此频道发消息 5.在频道中还可以看到其他人的发言,即公共消息群内人均可以看到 6.当用户退出,在他下一次登录之后,可以查阅在他不在的这段时间当中,大家都发了生命消息。


协议选择

要想实现网页聊天,则需要一个应用层协议进行数据传输 1号备选协议HTTP:

http可以实现消息推送√

但http适合网页聊天吗? 答案是,可以实现,但耗费资源较为多,且效率低。 http是典型的一问一答模式,即如果客户端没有主动向服务器请求,服务器是不会给予响应的。 但http中又有轮询(规定一定周期:1s一次询问,让客户端向服务器发送请求),这样看起来就像是服务器主动给客户端推送消息一样,但本质上还是一问一答,只不过问的那一步被隐藏了起来。 但这种消息推送效率相当低,因为没有用户会不间断的发消息,客户端大部分情况都是没有新消息的,所以在没有消息发送时,问服务器 就是在做无用功。且如果采用短轮询连接成本也相当大。 因此http不适合用于聊天系统。

http适合消息推送×

2号备选协议WebSocket:

websocket可以实现消息推送√

那websocket适合网页聊天吗? 首先websocket是一个应用层协议,其次websocket可以完成不问就答 。 websocket允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

websocket适合消息推送√

好啦~ 协议选择完毕~~


如何使用 WebSocket

问题一,怎么让应用层使用WebSocket协议?

WebSocket 是独立的、创建在 TCP 上的协议。 Websocket 是基于Http协议.HTML5 Websocket 通过HTTP/1.1 协议的101状态码进行握手。 为了创建Websocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)。

由于以上原因可以得出,WebSocket是需要通过升级http协议才能进行使用。

升级协议:客户端尝试针对服务器发送ws://这样的url请求时,此时发的仍然是一个HTTP请求,但是请求中会带有Upgrade字段来请求升级协议,服务器端如果同意升级,就会返回一个101状态码的响应报文。

此时websocket连接建立完毕,就可以传输数据。

客户端使用websocket也需要url来指定服务器的位置 这个url是以ws://开头,ws是websocket的缩写

问题二,TCP socket API主要操作和web socket API主要操作有什么区别?
TCP socket API主要操作web socket API主要操作connectconnectcloseclosewritesendreadreceive websocket api类似于原生本质上是给浏览器提供了更加灵活的网络传输机制 (本来在网页中只能操作HTTP协议)websocket给网页更多的操作网络的方式websocket想象成一个类似于tcp这样的一个基础协议,在这个基础协议上,用户可以构件更复杂的网络通信程序=>例如实现消息推送
问题三,WebSocket的配置?

在使用WebSocket

第一步就是要引入第三方依赖,使用maven进行管理 配置 :

<!-- https://mvnrepository.com/artifact/javax.websocket/javax.websocket-api --> <dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.1</version> <scope>provided</scope> <!--表示开发时需要使用,部署到Tomcat上的时候,就不需要带此jar包(tomcat内置这个jar包)--> </dependency>

第二步使用注解**@ServletEndpoint**

在web开发中,可以使用@ServletEndpoint注解修饰指定的类,同时在注解中使用value参数来指定一个具体的路径 后续html页面就可以通过这个路径来访问到服务器

问题四,webSocket中的方法以及应用
服务器(java)
方法 以及作用对应注解(不需要程序员主动调用)a> onOpen,建立连接时使用@OnOpenb> onClose,关闭连接时使用@OnClosec> onMessage,收到消息时调用@OnMessaged> onError,触发异常错误时调用@OnError
客户端(JS)
方法 以及作用a)onpen,建立连接时调用b)onclose,关闭连接时使用c) onmessage,收到消息时调用d) onerror,触发异常错误时调用

如何让服务端主动发消息

1.设计客户端和服务端 2.服务器如何给客户端返回消息

服务器端收到客户端发的消息,就会触发onMessage函数,调用sendText就把数据返回给了浏览器 浏览器收到服务器的响应之后,就会触发onmessage函数,从而打印收到的内容

session.getBasicRemote().sendText(""); //把一个文本数据写回到浏览器 //需要程序员主动调用,调用这个方法就能写回数据,无需客户端先发送请求

websocket.send()给服务器发送数据


数据库设计思路

1.围绕软件需求,分析实体

实体有: User(用户信息) Channel(频道) Massage(消息)

2.分析实体之间的关系(一对一,一对多,多对多)

User和Channel:多对多(但由于还未实现关注频道功能,暂时的将其简化为任何用户都可进入所有频道) User和Message:一对多 Channel和Message:一对多(未实现消息群发)

3.画E-R图

4.创建表结构
create database chatroom; use chatroom; drop table if exists user; create table user( userId int primary key auto_increment, name varchar (50) unique , password varchar (50), nickname varchar (50), lastLogout Datetime --lastLogout 上次退出的时间,用来实现历史记录功能 ); drop table if exists channel; create table channel( channelId int primary key auto_increment, channelName varchar (50) ); drop table if exists message; create table message( messageId int primary key auto_increment, userId int,--谁发送的消息 channelId int, context text,--消息正文 sendTime datetime --消息发送时间 )
5.连接数据库,并实现数据库中的相关代码
创建DBUtil类管理连接 public static DataSource getDataSource() { // 获取到这个单例的 DataSource 实例. if (dataSource == null) { synchronized (DBUtil.class) { if (dataSource == null) { dataSource = new MysqlDataSource(); // 必须要告诉代码, 数据库是谁, 以啥样的方式登陆上去. ((MysqlDataSource)dataSource).setURL(URL); ((MysqlDataSource)dataSource).setUser(USERNAME); ((MysqlDataSource)dataSource).setPassword(PASSWORD); } } } return dataSource; } public static Connection getConnection () { try { return getDataSource().getConnection(); } catch (SQLException e) { e.printStackTrace(); } return null; } 在IDEA中创建实体类


设计API(个人所设API仅供参考)

确定客户端都能给服务端发哪些种类的请求。 服务器收到请求之后该返回什么样的响应。

1. 用户注册

请求格式 POST /register { name:xxx, password:xxx, nickName:xxx } 响应格式 HTTP/1.1 200 OK { ok:1, //1表示成功,0表示失败(此处约定方式只是常见的方式之一当然也可以约定成其他格式) reason:xxx //如果失败,reason就是一个具体的失败原因 }

2. 登录

请求格式 POST /login { name:xxx, password:xxx } 响应格式 HTTP/1.1 200 OK { ok:1, reason:xxx, userId:1, name:xxx, nickName:xxxx }

3. 检测登录状态

请求格式 GET / login Cookie:JSESSION=XXXXX 响应格式 HTTP /1.1 200 OK { ok:1, reason:xxx, userId:1, name:xxx, nickName:xxx }

4.注销功能

未实现!

5.新增频道

请求格式 POST /channel { channelName:xxx } 响应格式 HTTP/1.1 200 OK { ok:1, reason:xxxx }

6.获取频道列表

请求格式 GET /channel 响应格式 HTTP/1.1 200 OK [ { channelID;1, channelName:“ASRM” }, { channelID;2, channelName:“ASMR” } ]

7.删除频道

请求格式 DELETE /channel?channlId=1 响应格式 HTTP/1.1 200 ok{ }

8.建立websocket链接(传输消息的准备工作)

这就不是HTTP协议了 ws://[ip]:[port]/message/{userId} 每个登录中的用户,都需要有自己的连接,把连接之间使用userId来区分。

9.发送/接收消息格式

为了简单起见,把发送和接受格式统一成一样的了(按理说应该不一样) JSON:当前这个message是通过websocket来传输,而不是HTTP协议了。 { userId:1,//消息是谁发的 nickName:xxx,//消息发送者的昵称 channelId:xxx,//消息要往哪个频道发送 content:“123asd”,//消息内容 }

!待补充!!!

实现接口

测试接口

网上聊天室测试

最新回复(0)