在知乎上看了一篇文章,感觉受益匪浅。认真迭代一个项目比盲目的多写几个app的收益会更大,还有就是认真的夯实基础,拿offer面试的时候也会更注重基础,还有半年的时间来准备,也就不打算再写其它的项目了,博客方面的话就不定期来写写最近的学习心得,还有这个项目的进展吧。每篇文章的最后都会分析一下目前的缺点以及短期计划。
项目方向:IM(Instant Messenge)聊天项目
项目要求:Android端:UI、消息持久化(读写、缓存)、长链接网络(解决NAT 超时、DHCP续租、参考TLS1.3的安全机制、私有协议设计、大文件分片、失败重试机制设计)、多线程、消息推送、消息同步等。
服务端:持久化(表设计、分库机制)、发送队列、连接管理、并发、负载均衡等。
下面开始进入正文:截至本篇文章、已经实现了网页端、服务器端(NodeJs)、和android端的最简单基础的功能,只能够实现简单的聊天。网页地址为:http://www.spwannasing.cn:4000/ 网页端目前只打算用来测试、不会过多的投入。
如此迅速的就能实现三个端的核心功能,还是用了不少外部库和框架的。比如android端,用了一个socket的支持库,实现和服务器连接。这一点要反思,下面几天要研究一下这个socket源码,还有就是相关的一些传输协议、原来太年轻不重视的计算机网络的基础知识还是相当重要的,切记切记啊。
先来看一下服务端,直接上代码:
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
users = [];
app.use('/', express.static(__dirname + '/www'));
server.listen(process.env.PORT || 4000);
io.sockets.on('connection', function(socket) {
socket.on('login', function(nickname) {
if (users.indexOf(nickname) > -1) {
socket.emit('nickExisted');
} else {
//socket.userIndex = users.length;
socket.nickname = nickname;
users.push(nickname);
socket.emit('loginSuccess');
io.sockets.emit('system', nickname, users.length, 'login');
};
});
//user leaves
socket.on('disconnect', function() {
if (socket.nickname != null) {
//users.splice(socket.userIndex, 1);
users.splice(users.indexOf(socket.nickname), 1);
socket.broadcast.emit('system', socket.nickname, users.length, 'logout');
}
});
//new message get
socket.on('postMsg', function(msg, color) {
socket.broadcast.emit('newMsg', socket.nickname, msg, color);
});
//new image get
socket.on('img', function(imgData, color) {
socket.broadcast.emit('newImg', socket.nickname, imgData, color);
});
});
代码很清晰简单,首先是监听4000端口,然后用socket通讯,监听 对应String事件。也没有什么数据库和持久化,所以直接emit出去信息就可以了。
知识点:利用Socket建立网络连接的步骤
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。
为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。
而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
然后是网页端:就展示与服务器交互的一部分吧,其余的给出GitHub:https://github.com/CallMeSp/MyChattingRoom_backend-Webend.git 服务器端和网页端的内容都在里面。
window.onload = function() {
var hichat = new HiChat();
hichat.init();
};
var HiChat = function() {
this.socket = null;
};
HiChat.prototype = {
init: function() {
var that = this;
this.socket = io.connect();
this.socket.on('connect', function() {
document.getElementById('info').textContent = 'get yourself a nickname :)';
document.getElementById('nickWrapper').style.display = 'block';
document.getElementById('nicknameInput').focus();
});
this.socket.on('nickExisted', function() {
document.getElementById('info').textContent = '!nickname is taken, choose another pls';
});
this.socket.