版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
实验报告
实验名称:《计算机网络》课程设计(实验二)学生姓名:专
业:物联网工程班
级:物联1301
一、实验目的与实验要求1、实验目的
使用并发服务器的模式,实现同时与多个客户端通信的服务器程序。
2、实验要求三个作业中,至少要有一个基于c语言完成,其余两个作业可用C++,C#,JAVA等设计完成。本课程设计基于socket网络编程接口开发服务端与客户端,通过TCP/IP协议进行两者之间的通信。任务二:服务器开放并监听固定端口,多个客户端连接至服务器开放的指定端口,连接成功后向服务器端发送信息,并显示在标准输出上。二、实验设备(环境)及要求由于本人使用web开发:开发环境为node.js搭建服务器端,使用express和socket.io框架实现客户端与服务器端通信。三、实验内容与步骤3.1.课题任务功能分析,包括数据包的格式分析对整体实现方式的综述:由于本人使用的并非C++或者Java语言,而是web开发中的javascript语言进行功能的实现,因此特对具体实现方式进行说明:Node.js介绍:Node.js是一个Javascript运行环境(runtime)。实际上它是对GoogleV8引擎进行了封装。V8引擎执行Javascript的速度非常快,性能非常好。Node.js可以创建性能优良的http协议/TCP/UDP服务器。Express模块介绍:express是node.js中管理路由响应请求的模块,根据请求的URL返回相应的HTML页面。这里我们使用一个事先写好的静态页面返回给客户端,只需使用express指定要返回的页面的路径即可。如果不用这个包,我们需要将HTML代码与后台JavaScript代码写在一起进行请求的响应,不太方便。Socket.io介绍:Node.js中使用socket的一个包。使用它可以很方便地建立服务器到客户端的sockets连接,发送事件与接收特定事件。服务器端:使用socket.io,其前后端句法是一致的,即通过socket.emit()来激发一个事件,通过socket.on()来侦听和处理对应事件。这两个事件通过传递的参数进行通信。首先引入express模块、socket模块、http模块创建一个服务器,设置本地端口为3000,引入socket模块并绑定到服务器。在socket部分:首先需要一个全局函数io.socket.on来处理所有与客户端连接时候的状态。需要针对不同的情况设置不同的处理函数socket.on,根据本次任务的需求,一共暂时设置了三种事件:客户端登录事件:每一个客户端需要输入自己的昵称进行登录,将所有用户的昵称压入一个user数组进行管理,保证没有重复的昵称才可成功登陆。成功登陆后服务器把登录信息广播给所有客户端。客户端退出事件:每一个客户关闭当前页面视为退出,会通知服务器,服务器把该用户退出的信息广播给所有客户端。客户端发送消息处理事件:服务器把一个客户端发来的消息广播给所有客户端。客户端:首先添加初始化方法:包括建立到服务器的socket连接,监听socket的connect事件,连接到服务器后,接收服务器发来的消息。接着添加新的原型方法:负责处理发送到服务器端的消息。
3.2.程序流程图
服务器端:客户端:3.3.程序清单程序目录结构:Nodechat——pp——css ——img ——js ——index.html ——server.js 服务器端代码:文件名:server.js/**
*
Created
by
tracy
on
16/5/22.
*///引入express模块var
express
=
require('express'),
app
=
express(),//创建一个服务器
server
=
require('http').createServer(app);
io
=
require('socket.io').listen(server);//引入socket.io模块并绑定到服务器
users=[];//保存所有在线用户的昵称
app.use('/',
express.static(__dirname
+
'/app'));
//指定静态HTML文件的位置//监听8080端口
server.listen(3000);
console.log('server
started');//socket部分
io.sockets.on('connection',
function(socket)
{
//接收并处理客户端发送的foo事件
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');//向所有连接到服务器的客户端发送当前登陆用户的昵称
}
});
//断开连接的事件
socket.on('disconnect',
function()
{
//将断开连接的用户从users中删除
users.splice(socket.userIndex,
1);
//通知除自己以外的所有人
socket.broadcast.emit('system',
socket.nickname,
users.length,
'logout');
});
//接受客户端发来的消息
socket.on('postMsg',
function(msg)
{
//将消息发送到除自己外的所有用户
socket.broadcast.emit('newMsg',
socket.nickname,
msg);
});
});客户端代码:①客户端逻辑实现js文件:index.js:/**
*
Created
by
tracy
on
16/5/22.
*///定义了整个程序需要使用的类NodeChat,之后处理消息显示消息等所有业务逻辑均写在这个类里window.onload
=
function()
{
//实例并初始化程序
var
nodechat
=
new
NodeChat();
nodechat.init();};//定义nodechat类var
NodeChat
=
function()
{
this.socket
=
null;};//向原型添加业务方法NodeCtotype
=
{
init:
function()
{//此方法初始化程序
var
that
=
this;
//建立到服务器的socket连接
this.socket
=
io.connect();
//监听socket的connect事件,此事件表示连接已经建立
this.socket.on('connect',
function()
{
//连接到服务器后,显示昵称输入框
document.getElementById('wrapper_login').style.display
=
'block';
document.getElementById('input_name').focus();
});
this.socket.on('nickExisted',
function()
{
document.getElementById('hint').textContent
=
'昵称被占用啦,请换一个吧~';
//显示昵称被占用的提示
});
this.socket.on('loginSuccess',
function()
{
document.title
=
'nodechat
|
'
+
document.getElementById('input_name').value;
document.getElementById('wrapper_chat').style.display
=
'block';
document.getElementById('wrapper_login').style.display
=
'none';//隐藏遮罩层显聊天界面
document.getElementById('input_msg').focus();//让消息输入框获得焦点
});
this.socket.on('system',
function(nickName,
userCount,
type)
{
//判断用户是连接还是离开以显示不同的信息
var
msg
=
nickName
+
(type
==
'login'
?
'
joined'
:
'
left');
var
p
=
document.createElement('h2');
p.textContent
=
msg;
document.getElementById('historyMsg').appendChild(p);
//指定系统消息显示为红色
that._displayNewMsg('system
',
msg,
'red');
//将在线人数显示到页面顶部
document.getElementById('status').textContent
=
userCount
+
(userCount
>
1
?
'
users'
:
'
user')
+
'
online';
});
this.socket.on('newMsg',
function(user,
msg)
{
that._displayNewMsg(user,
msg);
});
//昵称设置的确定按钮
document.getElementById('btn_login').addEventListener('click',
function()
{
var
nickName
=
document.getElementById('input_name').value;
//检查昵称输入框是否为空
if
(nickName.trim().length
!=
0)
{
//不为空,则发起一个login事件并将输入的昵称发送到服务器
that.socket.emit('login',
nickName);
}
else
{
//否则输入框获得焦点
document.getElementById('input_name').focus();
};
},
false);
//发送消息
document.getElementById('btn_send').addEventListener('click',
function()
{
var
messageInput
=
document.getElementById('input_msg'),
msg
=
messageInput.value;
messageInput.value
=
'';
messageInput.focus();
if
(msg.trim().length
!=
0)
{
that.socket.emit('postMsg',
msg);
//把消息发送到服务器
that._displayNewMsg('me',
msg);
//把自己的消息显示到自己的窗口中
};
},
false);
},
//向原型添加业务方法
_displayNewMsg:
function(user,
msg,
color)
{
var
container
=
document.getElementById('historyMsg'),
msgToDisplay
=
document.createElement('h2'),
date
=
new
Date().toTimeString().substr(0,
8);
msgToDisplay.style.color
=
color
||
'#000';
msgToDisplay.innerHTML
=
user
+
'<span
class="timespan">('
+
date
+
'):
</span>'
+
msg;
container.appendChild(msgToDisplay);
container.scrollTop
=
container.scrollHeight;
}};②客户端html页面文件名:index.html:<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metaname="author"content="Wangwurong">
<title>NodeChat</title>
<linkrel="stylesheet"href="css/index.css">
</head>
<body>
<divclass="banner">
<imgsrc="img/mylogo.png"/>
<h1>NodeChat</h1>
<h2id="status"></h2>
</div>
<divid="historyMsg"></div>
<divid="wrapper_chat">
<div><textareaid="input_msg"placeholder="请输入聊天内容"></textarea></div>
<div><aid="btn_send"class="btn">发送</a></div>
</div>
<divid="wrapper_login">
<h1id="hint">connectingtoserver...</h1>
<div><inputclass="input_text"type="text"placeholder="请输入昵称"id="input_name"/></div>
<div><aid="btn_login"class="btn">进入聊天</a></div>
</div>
<scriptsrc="/socket.io/socket.io.js"></script>
<scriptsrc="js/index.js"></script>
</body>
</html>③客户端样式文件:文件名:index.lessbody{
background-color:rgb(228,228,228);
}
textarea{
outline:none;
width:30%;
height:80px;
border:1pxsolid#D2D2D2;
border-radius:10px;
padding:10px;
font-size:15px;
}
h1{
font-family:cursive;
}
h2{
font-family:monospace;
font-size:20px;
margin:2px0;
}
.banner{
text-align:center;
margin-top:40px;
img{
width:100px;
height:100px;
}
}
.btn{
display:block;
width:31%;
margin:10pxauto;
background-color:#333333;
border-radius:6px;
height:40px;
line-height:40px;
color:#ffffff;
cursor:pointer;
}
.input_text{
outline:none;
width:30%;
padding:10px5px;
border-radius:8px;
border:1pxsolid#D2D2D2;
font-size:15px;
}
#wrapper_chat{
display:none;
}
#wrapper_chat,#historyMsg{
text-align:center;
max-height:200px;
overflow:scroll;
width:80%;
margin:15pxauto;
}
#w
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 河南蛋糕店运营方案
- 2024年高考英语分类题库考点4 语法填空
- 2026 儿童适应能力社交文化融合课件
- Q热诊断与管理指南Q热抗生素及剂量总结2026
- 护理伦理学基础
- 数字时代酒店企业全面预算管理的优化策略探究
- 2026年中国石化招聘模拟试卷
- 教育机构前台服务体系构建
- 工法开发方案
- 水泥厂项目BIM技术应用方案
- 第四章 第一节区域发展对交通运输布局的影响 学案-2025-2026学年 高中地理人教版 必修第二册
- 曹妃甸职业技术学院教师招聘考试试题及答案
- 舒氏针灸内部课件
- 癫痫患者的记忆改善策略与实践路径
- 急诊科窒息患者现场抢救流程
- GB/T 46199-2025非开挖铺设用球墨铸铁管
- 互联网域名基础知识培训课件
- 信创基础知识培训课件
- 年产1000万件日用陶瓷陶瓷厂工艺设计
- 宿迁网约车考试题及答案
- 贵州概算调整管理办法
评论
0/150
提交评论