前言

什么是Websocket呢?

我们都知道在Http协议中,客户端与服务器端的通信是靠客户端发起请求,然后服务器端收到请求再进行回应,这个过程中,客户端是主动的,服务器端是被动的。Websocket协议就不一样了,它是基于TCP的一种新的网络协议,它与Http协议不同之处就在于Websocket能实现服务器端主动推送消息到客户端,服务器端与客户端都能发起通信,这一次,服务器端终于也拥有了主动权。

什么是socket.io?

socket.io封装了Websocket以及其他的一些协议,并且实现了Websocket的服务端代码。同时还有很强的兼容性,兼容各种浏览器以及移动设备。有了它,我们能更方便快捷地实现服务器端与客户端之间的实时通讯。

实现功能简述

要实现多人聊天室的核心就是区分当前用户发送的消息与其他用户发送的消息,在这里我通过用户登录使用的用户名来进行区分。所以用户进入首先展示登录页面。

登录成功之后,新用户加入聊天室

如果用户重名,会弹出提示,保持吴彦祖的登录状态,我们再打开一个标签,输入“吴彦祖”查看效果

只有当昵称唯一时,才允许登录,我们再登录一个查看效果

可以看到,当新用户登录时,其他在线用户会收到提示,接下来就是发送消息了

发送的消息是实时推送的,当前用户发送的消息与其他用户发送的消息对话框做了区分。

当用户退出时,系统也会给出提示,效果如下

怎么样,有没有兴趣继续了解呢?下面就开始着手开发吧。

环境搭建

1.安装node.js

后端服务是用的node.js,所以我们首先要进行安装,安装方法很简单,我在之前一篇文章也提过。首先在node.js官网下载稳定版本,下载完成后点击安装,安装过程也很简单,一直next即可,安装完成会自动添加node及npm环境变量。

检验是否安装成功,在cmd输入命令node -v,回车 及 npm -v,回车,如出现下图所示版本信息,表示安装成功

2.新建项目文件夹,安装socket.io

新建文件夹chatroom,在这里我把它建到D盘根目录下。打开cmd,定位到刚建的chatroom文件夹下,输入npm install socket.io安装socket.io

安装完成之后,可以看到文件夹下多了node_modules文件,里面全是刚下载的socket.io依赖包。

3.新建页面

在chatroom文件夹下新建页面文件index.html,样式chat.css,后端jsapp.js,前端jschat.js,并下载jquery.min.js,socket.io.js。再下载一张图片作为用户头像,放在images/user/下。

目录结构如下

好了,环境搭建完成,开始撸码吧。

项目搭建

1.构建node服务器

在app.js里面构建服务器

/*app.js*/

/*构建http服务*/

var app = require('http').createServer()

/*引入socket.io*/

var io = require('socket.io')(app);

/*定义监听端口,可以自定义,端口不要被占用*/

var PORT = 8081;

/*监听端口*/

app.listen(PORT);

console.log('app listen at'+PORT);

接着启动服务

打开cmd,定位到app.js所在目录,输入node app.js,如图所示,打印出了我们写的内容,表示服务启动成功。

2.建立服务端socket连接监听

先给大家简单讲一下服务器端与客户端通信的基本方法

大家可以看一下socket.io的文档

(1)socket.emit

客户端与服务器端之间发送消息是用emit

例如客户端向服务端发送登录请求

socket.emit('login',{username:uname}) login是自定义的事件,后面是带的参数

(2)socket.on

服务器端要接收客户端发送的login事件,就得对该事件进行监听

socket.on('login',function(data){})在回调函数中进行处理

同理,服务器端也可以向客户端发送事件,只要客户端也对该事件进行监听就行

(3)io.sockets.emit

服务器端向连接的所有客户端发送消息得用io.sockets.emit

(4)socket.broadcast.emit

给除了自己以外的客户端广播消息

/*app.js*/

/*构建http服务*/

var app = require('http').createServer()

/*引入socket.io*/

var io = require('socket.io')(app);

/*定义监听端口,可以自定义,端口不要被占用*/

var PORT = 8081;

/*监听端口*/

app.listen(PORT);

/**

*监听客户端连接

*io是我们定义的服务端的socket

*回调函数里面的socket是本次连接的客户端socket

*io与socket是一对多的关系

*/

io.on('connection', function (socket) {

/*所有的监听on,与发送emit都得写在连接里面,包括断开连接*/

})

console.log('app listen at'+PORT);

3.前端页面

index.html页面中需引入socket.io.js,socket.io.js下载地址

/*index.html*/

聊天室

/*登录界面*/

用户登录

登录

/*聊天界面,一开始隐藏,用户登录成功后再显示*/

多人聊天室

发送

4.样式

样式可以自己编写,我这里随便写了一下

/*公共样式*/

*{padding:0; margin:0;}

html,body{width:100%;height: 100%;}

.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}

.clearfix{*zoom:1}

.cred{color:#f03e3e;}

.cgreen{color:#459d36;}

.hide{display:none;}

.fr{float:right;}

.fl{float: left;}

.rela{position: relative;}

.abs{position:absolute;}

h1{position: fixed; z-index:20; width: 100%; height:50px; line-height:50px; font-size:20px; left: 0; top: 0; background: #000; color: #fff;}

/*登录界面*/

.login-wrap{background:#e7e7e7;width:100%;height:100%; text-align:center;}

.login-con{padding-top: 50px;}

.login-con h3{margin-bottom: 20px;}

.login-con input{width:60%; display:block; margin:0 auto; height: 40px; line-height: 40px; margin-bottom: 20px;}

.login-con button{width:60%;display:block; margin:0 auto; height: 40px; line-height:40px; border:none; background:#459d36; color:#fff; border-radius:5px;}

/*聊天界面*/

.chat-wrap{width: 100%; height: 100%;overflow-y:scroll; background:#e7e7e7; text-align:center;}

.chat-con{padding: 50px 0; background:#e7e7e7;}

.chat-con p{display:inline-block; padding:5px 10px; background:#999;border-radius:5px; color:#fff; margin:5px 0;}

.bottom{position:fixed;bottom:0; left: 0; width:100%; height: 50px; background: #fff;}

.bottom input{width: 78%; height: 50px; line-height: 50px; float:left;border:none;}

.bottom button{width: 20%;height: 50px; float: right; border:none; background:#459d36;color: #fff;}

.chat-item{width:100%; margin-bottom:20px;}

.item-right .message{background: #62b900;}

.item-left .message{background: #fff; margin-top:20px;}

.item-left .img{margin-right:10px;}

.item-left .uname{font-size:12px; left:50px; top:0;}

.chat-item .message{width:60%;display:block; padding:10px;border-radius:5px; margin-right:10px;}

.chat-item .img{display:inline-block; width:40px; height:40px; background:url(../images/user/user.jpg) no-repeat; background-size:100% 100%;}

5.逻辑编写

(1)登录

客户端

浏览器端将获得的用户输入的昵称信息,发送到服务器端,告诉服务器端我要触发login事件。

在客户端chat.js中发送登录事件

/*chat.js*/

$(function(){

/*建立socket连接,使用websocket协议,端口号是服务器端监听端口号*/

var socket = io('ws://localhost:8081');

/*定义用户名*/

var uname = null;

/*登录*/

$('.login-btn').click(function(){

uname = $.trim($('#loginName').val());

if(uname){

/*向服务端发送登录事件*/

socket.emit('login',{username:uname})

}else{

alert('请输入昵称')

}

})

})

服务器端

服务器端监听login事件,在后台打印出获取到的昵称信息。

在服务器端app.js中监听登录事件

/*app.js*/

var app = require('http').createServer()

var io = require('socket.io')(app);

var PORT = 8081;

app.listen(PORT);

io.on('connection', function (socket) {

/*监听登录*/

socket.on('login',function(data){

console.log(data)

})

})

console.log('app listen at'+PORT);

注:更改了app.js,需再次启动服务才能看见效果

打开cmd,按Ctrl+C退出上次服务,再次输入node app.js启动服务,打开浏览器,查看效果

可以看到,点击登录按钮时,服务器端打印出了接收到的用户名信息,没问题,继续往下写登录成功事件。

(2)登录成功与失败

由于没有使用到数据库,所以我们就定义一个用户数组,用户每次登录之后,我们就判断该昵称是否已存在,如果已存在就弹出提示,转到登录失败事件,如果该昵称不存在数组里面,就视为新用户,转到登录成功事件,并且将该昵称存入数组。

服务器端

/*app.js*/

var app = require('http').createServer()

var io = require('socket.io')(app);

var PORT = 8081;

/*定义用户数组*/

var users = [];

app.listen(PORT);

io.on('connection', function (socket) {

/*是否是新用户标识*/

var isNewPerson = true;

/*当前登录用户*/

var username = null;

/*监听登录*/

socket.on('login',function(data){

for(var i=0;i

if(users[i].username === data.username){

isNewPerson = false

break;

}else{

isNewPerson = true

}

}

if(isNewPerson){

username = data.username

users.push({

username:data.username

})

/*登录成功*/

socket.emit('loginSuccess',data)

/*向所有连接的客户端广播add事件*/

io.sockets.emit('add',data)

}else{

/*登录失败*/

socket.emit('loginFail','')

}

})

})

console.log('app listen at'+PORT);

客户端

/*chat.js*/

$(function(){

/*建立socket连接,使用websocket协议,端口号是服务器端监听端口号*/

var socket = io('ws://localhost:8081');

/*定义用户名*/

var uname = null;

/*登录*/

$('.login-btn').click(function(){

uname = $.trim($('#loginName').val());

if(uname){

/*向服务端发送登录事件*/

socket.emit('login',{username:uname})

}else{

alert('请输入昵称')

}

})

/*登录成功*/

socket.on('loginSuccess',function(data){

if(data.username === uname){

checkin(data)

}else{

alert('用户名不匹配,请重试')

}

})

/*登录失败*/

socket.on('loginFail',function(){

alert('昵称重复')

})

/*新人加入提示*/

socket.on('add',function(data){

var html = '

系统消息:'+data.username+'已加入群聊

';

$('.chat-con').append(html);

})

/*隐藏登录界面 显示聊天界面*/

function checkin(data){

$('.login-wrap').hide('slow');

$('.chat-wrap').show('slow');

}

})

再次重启服务,打开浏览器查看效果,登录成功效果如上面图2所示,登录失败效果如上面图3所示。

(3)退出登录

退出登录,只需服务器端在用户数组里面删除退出的用户即可。

服务器端

/*app.js*/

/*退出登录*/

/*写在io.on('connection', function (socket) {})里面*/

socket.on('disconnect',function(){

/*向所有连接的客户端广播leave事件*/

io.sockets.emit('leave',username)

users.map(function(val,index){

if(val.username === username){

users.splice(index,1);

}

})

})

客户端

/*chat.js*/

/*退出群聊提示*/

socket.on('leave',function(name){

if(name != null){

var html = '

FBI warning:'+name+'已退出群聊

';

$('.chat-con').append(html);

}

})

(4)发送消息

客户端

/*chat.js*/

/*发送消息*/

$('.sendBtn').click(function(){

sendMessage()

});

$(document).keydown(function(event){

if(event.keyCode == 13){

sendMessage()

}

})

function sendMessage(){

var txt = $('#sendtxt').val();

$('#sendtxt').val('');

if(txt){

socket.emit('sendMessage',{username:uname,message:txt});

}

}

服务器端

/*app.js*/

socket.on('sendMessage',function(data){

io.sockets.emit('receiveMessage',data)

})

客户端

/*chat.js*/

/*接收消息*/

socket.on('receiveMessage',function(data){

showMessage(data)

})

/*显示消息*/

function showMessage(data){

var html

if(data.username === uname){

html = '

'+data.message+'

'

}else{

html='

'+data.username+''+data.message+'

'

}

$('.chat-con').append(html);

}

到这里,一个简单的多人聊天室已基本实现了,先回顾一下准备工作

(1)下载node.js;

(2)安装socket.io;

npm install socket.io

(3)服务器端构建http服务,引入socket.io,并设置监听端口

var app = require('http').createServer()

var io = require('socket.io')(app);

var PORT = 8081;

app.listen(PORT);

(4)客户端进行socket连接,使用websocket协议

var socket = io('ws://localhost:8081');

再回顾一下整个逻辑流程:

(1)客户端获取用户输入昵称,发送给服务器端;

(2)服务器端接收昵称,判断是否新用户,是则发送登录成功事件,否则发送登录失败事件;

(3)客户端收到服务器端发送的登录成功或失败事件,进行相应处理;

(4)浏览器端获取登录用户输入的消息,将消息与用户昵称一起发送给服务器端;

(5)服务器端接收到用户发送的消息,广播该消息给当前连接的所有客户端;

(6)客户端接收服务器端发送来的消息,判断昵称是否是自己,进行相应对话框显示

最后附上github地址

socket多人聊天室c语言,WebSocket学习(一)——基于socket.io实现简单多人聊天室...相关推荐

  1. 使用nettyio+socket.io搭建简单的网页聊天室

    使用nettyio+socket.io搭建简单的网页聊天室 1 目录结构 2 maven 依赖配置 <project xmlns="http://maven.apache.org/PO ...

  2. 基于PHP实现一个简单的在线聊天功能(轮询ajax )

    基于PHP实现一个简单的在线聊天功能(轮询ajax ) 一.总结 1.用的轮询ajax 二.基于PHP实现一个简单的在线聊天功能 一直很想试着做一做这个有意思的功能,感觉复杂的不是数据交互和表结构,麻 ...

  3. C#上位机基础学习_基于SOCKET实现与PLC服务器的TCP通信(二)

    C#上位机基础学习_基于SOCKET实现与PLC服务器的TCP通信(二) 测试软件: TIA PORTAL V15.1 S7-PLCSIM ADVANCED V3.0 Visual Studio 20 ...

  4. socket.io php 聊天室,WebSocket学习(一)——基于socket.io实现简单多人聊天室

    前言 什么是Websocket呢? 我们都知道在Http协议中,客户端与服务器端的通信是靠客户端发起请求,然后服务器端收到请求再进行回应,这个过程中,客户端是主动的,服务器端是被动的.Websocke ...

  5. 基于PHP实现一个简单的在线聊天功能

    一直很想试着做一做这个有意思的功能,感觉复杂的不是数据交互和表结构,麻烦的是前端展..于是.. 需求分析 要实现功能,首先要做前端,经过对比其他网站的在线聊天功能,发现除了基本的聊天功能以外,还要注意 ...

  6. linux点对点聊天室的实现与设计心得,基于Socket接口的Linux与Windows网络聊天室设计与实现...

    陈洁 孟晓景 摘要:为了实现Linux与Windows跨平台通信,及时共享信息,构建了一个适用于跨平台的网络聊天室通信程序.先搭建跨平台通信环境,然后使用Socket套接字网络编程接口实现通信.整个系 ...

  7. [Nodejs]初探nodejs学习笔记- 如何使用nodejs搭建简单的UDP聊天功能

    2019独角兽企业重金招聘Python工程师标准>>> 何为UDP(User Datagram Protocol)? 从baidu摘过来一段:UDP,用户数据报协议,与所熟知的TCP ...

  8. 自学Java的人,如何系统全面的学习?

    最近,收到越来越多的人请教我说想转行做程序员,自学Java,但是Java的知识太多,不知道从何学起才好,那现在,我就来分享一下经过长时间积累的经验吧. 自学Java,本身会面临来自多方的压力,所以在走 ...

  9. 郑州计算机c语言培训机构,c语言入门学习选郑州哪家计算机专业学校

    C语言是一门稀缺的贵族语言,会C语言的被IT界高看,C语言的地位很高,学C语言确实难,但是有正确的方法成为C程序员是非常有效的,会C语言相当于拥有了一定地位,未来非常有前景,那么如何入门C语言呢?选择 ...

  10. 基于Socket的游戏服务器通信框架的设计与实现

    博客地址:blog.liujunliang.com.cn 开发工具:VS2017.Unity2017 本文介绍使用Socket/TCP来开发客户端与服务器端通信框架 博主使用过PhotonServer ...

最新文章

  1. Java 垃圾回收机制,你知多少??
  2. centos 忘记 root 密码
  3. ActiveMQ持久化到mysql
  4. KMP算法的java实现
  5. ms access to mysql_Access转MySQL工具
  6. Vim/Vi常用操作(第二版)
  7. c# 智能升级程序代码(1)
  8. 【Kudu-未解决】Kudu : Kudu error: Could not connect to a leader master. Client configured with 1 master
  9. non linear processor
  10. eviews建立时间序列模型_模型建立——时间序列 eviews协整检验(EG两步法(Engle-Granger))...
  11. Xftp6的安装与使用
  12. 全微分里dxy是怎么化成xdy+ydx
  13. RAM与ROM的特点和区别
  14. angular.js 增删改查练习2
  15. python中ix用法_Python:Pandas中的ix用法详细解释
  16. 1.初识elasticsearch
  17. css: 照片有如层叠效果
  18. 【AI人工智能】AI绘画能取代设计师?
  19. 微信小程序 - [完整源码] 全屏左右菜单联动效果,左侧分类与右侧内容联动,类似美团饿了么的点餐页面 “左边菜单,右边内容“ 效果(开箱即用的示例源码,代码干净整洁且注释详细)
  20. Dearpygui制作Linux上SSD测试工具集合

热门文章

  1. java reader类子类_Java之InputStreamReader类的实现
  2. type 与 interface 的区别
  3. 苹果开发证书导出P12的问题
  4. Elasticsearch分布式引擎7.x,2021黑马详细课程笔记
  5. 图论1:哥尼斯堡七桥问题的证明
  6. 计算机技术与软件专业技术资格 (水平) 考试 - 报考指南
  7. python的镜像安装和设置
  8. 计算机组成原理符号标志,计算机组成原理之数据的表示及运算
  9. 互联网常见错误代码(如404)
  10. 阿里云宽带是怎么按流量进行计费的?