1.简单介绍下TCP/IP

TCP/IP是互联网相关协议的集合,分为以下四层:应用层、传输层、网络层、数据链路层。

分成四层的好处是,假如只有一层,某个地方需要改变设计时,就必须把所有整体替换掉,而分层之后只需把变动的层替换掉即可。

2. 服务端编程

node提供了net模块来实现tcp编程。主要分为服务端编程和客户端编程两部分,先来写服务端的:

监听客户端连接

先引入net模块,再通过 net.createServer 创建一个TCP服务器,服务器可以监听一个connection事件。

net.createServer([options][, connectionListener])

  • options<Object>

    • allowHalfOpen<boolean> 表明是否允许半开的 TCP 连接。默认值: false
    • pauseOnConnect<boolean> 表明是否应在传入连接上暂停套接字。默认值: false
  • connectionListener<Function> 自动设置为 'connection' 事件的监听器

我们先不传参数:

var net = require('net');
//创建tcp服务器
var server = net.createServer(); //监听connect事件
server.on('connection', (socket) => {
socket.on('data',(data)=>{
console.log(data.toString(), 'data')
})
}) //设置监听端口
server.listen(8989); //设置监听时的回调函数
server.on('listening', (res)=>{
console.log('in listen...')
})

connection事件当有数据发送过来时会被触发。监听函数的参数是一个socket,用户可以使用它与客户端进行交互。

通过socket的data事件可以打印出发送过来的数据,在浏览器中打开 http://localhost:8989,浏览器会将请求头的信息发送到server,所以输出结果如下:

上面代码中,connection事件可以传入到createServer中,listen和listening可以合并,写成下面这种形式:

//第二种写法
var net = require('net');
//创建tcp服务器
var server = net.createServer((socket) => {
socket.on('data', (data) => {
console.log(data.toString(), 'data..')
})
});
//设置监听端口
server.listen(8989, (res) => {
console.log('in listen...')
});

除了listening和connect事件外,server还有如下事件:

  • close:TCP服务器关闭的时候触发,回调函数没有参数
  • error:TCP服务器发生错误的时候触发,回调函数的参数为error对象

接收数据和发送数据

通过socket的data事件接收数据,write方法发送数据

socket.write(data[, encoding][, callback])

//创建一个TCP服务器
var server = net.createServer((socket) => {
//'connect'事件的回调函数
console.log('客户端已连接');
socket.on('end', () => {
console.log('客户端已断开');
})
//接收来自客户端的数据
socket.on('data', (data) => {
console.log(data.toString(), 'data');
var readSize = socket.bytesRead;
console.log('the size of data is ' + readSize);
}) //向客户端写入数据
socket.write('hello\r\n'); //设置连接最大数量,可不设
server.maxConnection = 3; server.getConnections(function (err, count) { console.log('the count of clieent is ' + count); }); }) server.listen(8989, () => {
console.log('服务器已启动');
//获取地址信息
var address = server.address(); //获取地址端口
console.log('the port of server is ' + address.port);
console.log('the address of server is ' + address.address);
console.log('the ip family of server is ' + address.family);
})

我们先不写客户端的代码,先用telnet工具来当作客户端来测试上面代码

打开命令行工具输入 telnet localhost 8989

可以看到  socket.write('hello\r\n') 这句话已经生效了,服务端向客户端返回了hello,但这样肯定还不够,

3. 客户端编程

客户端编程比服务端简单,因为不用监听端口。只要把数据从指定的端口发出去就可以了。

net.createConnection(options[, connectListener]) 用来创建一个socket。第一个参数必填,要写发送的端口号,第二个参数是这个socket的 'connect'事件的回调函数

//创建一个客户端
var client = net.connect({ port: 8989 }, () => {
console.log('连接到服务器');
//向服务端发送数据
client.write('hello,i am from client');
}) //监听事件,当服务端发送数据过来时会触发该事件
client.on('data', (data) => {
console.log(data, 'data');
client.end()
}) client.on('end', () => {
console.log('已从服务器断开');
});

上面代码的client就是一个socket,所以可以监听data事件来获取服务端发送来的数据。然后socket也可以通过write来向服务端发送数据

4. 一个小的登录系统

利用上面的知识,可以实现一个小型的登录系统:

/*server.js*/
var net = require('net');
//这儿用一个对象来模拟数据库,保存用户名和密码
var user = {
admin: '123',
test: '333',
lucy: '222',
}
//临时变量保存用户输入的内容
var username = ''; var server = net.createServer((socket)=>{
console.log('服务器已连接');
socket.write('请输入用户名:');
socket.on('data',(data)=>{
//通过stdin输入的内容是buffer,需要转成字符串且清除空格
data = data.toString().trim();
if(!username){
if(user[data]){
socket.write('请输入密码:');
username = data;
}else{
socket.write('用户名不对,请输入用户名:');
}
}else {
if(user[username] === data){
socket.write('登录成功');
}else {
socket.write('密码不对,请输入密码:');
}
}
});
socket.on('close',data=>{
console.log(data);
})
}) server.listen(8899,()=>{
console.log('服务器监听8899端口中')
})
/*client.js*/
var net = require('net');
process.stdin.resume(); var client = net.createConnection({port: 8899},()=>{
//process.stdin可以获取到用户的输入
process.stdin.on('data',input=>{
client.write(input)
})
}) //这儿接收服务端的返回数据
client.on('data',data=>{
console.log(data.toString());
if(data.toString()==='登录成功'){
process.exit();
}
})

基于node的tcp客户端和服务端的简单通信的更多相关文章

  1. 基于开源SuperSocket实现客户端和服务端通信项目实战

    一.课程介绍 本期带给大家分享的是基于SuperSocket的项目实战,阿笨在实际工作中遇到的真实业务场景,请跟随阿笨的视角去如何实现打通B/S与C/S网络通讯,如果您对本期的<基于开源Supe ...

  2. linux epoll机制对TCP 客户端和服务端的监听C代码通用框架实现

    1 TCP简介 tcp是一种基于流的应用层协议,其“可靠的数据传输”实现的原理就是,“拥塞控制”的滑动窗口机制,该机制包含的算法主要有“慢启动”,“拥塞避免”,“快速重传”. 2 TCP socket ...

  3. 通过Socket实现TCP编程,用户登录之服务器相应客户端,客户端和服务端之间的通信

    服务器端: 1.创建ServerSocket对象,绑定监听端口: 2.通过accept()方法监听客户端请求: 3.建立连接后通过输入流读取客户端发送的请求信息; 4.通过输出流向客户端发送响应信息; ...

  4. 基于socket的客户端和服务端聊天简单使用 附Demo

    功能使用 服务端 分离一个不停接受客户端请求的线程 接受不客户端请求的线程中,再分离就收消息的线程 几大对象分别是 IPEndPoint IP终结点 服务端Socket,绑定终结点Bind,启动监听L ...

  5. 基于C#net4.5websocket客户端与服务端

    只支持win8以上系统以及windows server2012以上系统 最近在研究视频传输给浏览器,然后使用H5标签解码.视频流采用websocket传输.所以研究了一下C#的websocket. 首 ...

  6. 【转】C# client 与java netty 服务端的简单通信,客户端采用Unity

    http://blog.csdn.net/wilsonke/article/details/24721057 近日根据官方提供的通信例子自己写了一个关于Unity(C#)和后台通信的类,拿出来和大家分 ...

  7. Python socket编程客户端与服务端通信

    [本文出自天外归云的博客园] 目标:实现客户端与服务端的socket通信,消息传输. 客户端 客户端代码: from socket import socket,AF_INET,SOCK_STREAM ...

  8. Netty4 学习笔记之二:客户端与服务端心跳 demo

    前言 在上一篇Netty demo 中,了解了Netty中的客户端和服务端之间的通信.这篇则介绍Netty中的心跳. 之前在Mina 中心跳的使用是通过继承 KeepAliveMessageFacto ...

  9. 实验09——java基于TCP实现客户端与服务端通信

    TCP通信         需要先创建连接 - 并且在创建连接的过程中 需要经过三次握手        底层通过 流 发送数据 数据没有大小限制        可靠的传输机制 - 丢包重发 包的顺序的 ...

随机推荐

  1. 数据库锁(mysql)

    InnoDB支持表.行(默认)级锁,而MyISAM支持表级锁 本文着中介绍InnoDB对应的锁. mysql锁主要分为以下三类: 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高 ...

  2. Android一句话 | ViewGroup事件分发

    ViewGroup中可重写的关于事件分发的事件有dispatchTouchEvent,onTouchEvent,onInterceptTouchEvent和requestDisallowInterce ...

  3. Android WebView优化

    1.展示webview的activity可以另开一个进程,这样就能和我们app的主进程分开了,即使webview产生了oom崩溃等问题也不会影响到主程序,如何实现呢,其实很简单,在androidman ...

  4. Abp vnext EFCore 实现动态上下文DbSet踩坑记

    背景 我们在用EFCore框架操作数据库的时候,我们会遇到在 xxDbContext 中要写大量的上下文 DbSet<>; 那我们表少还可以接受,表多的时候每张表都要写一个DbSet, 大 ...

  5. 【刷题-LeetCode】221. Maximal Square

    Maximal Square Given a 2D binary matrix filled with 0's and 1's, find the largest square containing ...

  6. GoLang设计模式20 - 组合模式

    定义 组合模式是一种结构型设计模式. 当我们想把一组对象当做一个整体来处理时就可以考虑使用组合模式. 组合模式被视为是接口型设计模式是因为它将一组对象组装为一个树状结构.这个树状结构中的每个独立组件都 ...

  7. centos7 service iptables save 报错

    解决办法: 1.systemctl stop firewalld 2.yum install iptables-services 3.systemctl  restart iptables 4.ser ...

  8. 磁盘sda,hda,sda1,并行,串行

    1.sd,hd表示硬盘, a表示第一块盘, 1表示硬盘上的第一个分区 2.sd是Serial ATA Disk ,表示硬盘是scsi,SATA串行接口 hd是 hard disk,表示硬盘是IDE(也 ...

  9. 为什么 Redis 的查询很快, Redis 如何保证查询的高效

    Redis 如何保证高效的查询效率 为什么 Redis 比较快 Redis 中的数据结构 1.简单动态字符串 SDS 对比 c 字符串的优势 SDS可以常数级别获取字符串的长度 杜绝缓冲区溢出 减少修 ...

  10. 在EntityFrameworkCore中记录EF修改日志,保存,修改字段的原始值,当前值,表名等信息

    突发奇想,想把业务修改的所有字段原始值和修改后的值,做一个记录,然后发现使用EF可以非常简单的实现这个功能 覆盖父类中的 SaveShanges() 方法 public new int SaveCha ...