JavaScript工具类

基本类型

概述

  1. string、number、boolean、symbol有构造函数
  2. undefined、null无构造函数
  3. typeof null=="object",这是历史遗留问题;null仍是基本数据类型

构造函数

  • new Number(任意类型):任意类型转成十进制数
  • Number(任意类型):任意类型转成十进制数
  • new String(任意类型):任意类型转成string类型
  • String(任意类型):任意类型转成string类型
  • new Boolean(true)
  • Boolean(false)
  • Symbol("symbol")

调用原型方法

  • 调用方式1:("123").split("")
  • 调用方式2:let str="123"; str.split("")

Object类型

构造函数

  • new Object({})
  • Object({})
  • {}

函数方法

  • Symbol属性不可枚举
  • create、freeze、seal
  • assign(target,...args):把...args的可枚举属性赋值到target对象
  • getPrototypeOf、setPrototypeOf
  • defineProperties、defineProperty
  • keys:所有可枚举属性数组
  • values:所有可枚举属性的值数组
  • entries:所有可枚举属性的键值对数组
  • getOwnpropertySymbols:所有Symbol属性数组

原型方法

  • hasOwnProperty("xxx"):检查是否包括可枚举属性xxx
  • isPrototypeOf、propertyIsEnumerable
  • toString、valueOf、toLocaleString

使用

  • Object.seal(obj):obj不能添加和删除属性,但是可以修改属性值
  • Object.seal(arr):arrj不能添加和删除元素,但是可以修改元素值
  • Object.preventExtensions(obj):obj不能添加属性,能删除属性

Function类型

构造函数

  • const 函数名=new Function(参数1,参数2,……,函数体)
  • const 函数名=Function(参数1,参数2,……,函数体)
  • function 函数名(参数1,参数2,……){函数体}

原型对象

  • function fun(){}
  • fun.__proto__ === Function.prototype
  • fun.__proto__.proto === Object.prototype  

V8内置对象

Array函数方法

  • new Array(3)<=>[,,,]
  • Array.isArray(对象):判断对象是数组

 Array.from(类数组)<=>[...类数组]<=>Array.prototype.slice.call(类数组)

  • Array.from(字符串,fun?)
  • Array.from(Set集合,fun?)
  • Array.from(Map集合,fun?)
  • Arr.from({'0':1,'1',2,length:2},fun?)
Array.prototype.slice.call(类数组)
Array.prototype.map.call(类数组,(element) =>{ return element})
Array.prototype.filter.call(类数组,(element) =>{return true})

手写from
from(类数组){
    let arr=new Array(类数组.length)
    for(let i=0;i<类数组.length;i++){
        arr[i]=类数组[i]
    }
    return arr
}

手写map
map(类数组,fun){
    let arr=new Array(类数组.length)
    for(let i=0;i<类数组.length;i++){
        arr[i]=fun(类数组[i])
    }
    return arr
}

Array原型方法

不改变原数组

concat、join、toString、slice

filter、map、reduce、foreach

find、includes、indexOf、lastIndexOf

改变原数组

push、pop、shift、unshift、splice

sort、reverse、fill

回调函数参数

value:当前元素的值

index:当前元素的索引

arr:元素所属的数组对象

arr[5]

obj[5]

超出元素范围的元素==undefined

arr[5]<=>arr["5"]

obj={

    3:"Tom",    3自动转成字符串"3"

    2:"Jack",    2自动转成字符串"2",

    5:"good"    5自动转成字符串"5",

}

obj[5]<=>obj["5"]

arr.splice(

    index, 删除起始索引

    num,   删除元素数量

    add1,  添加的元素1

    add2   添加的元素2

):删除元素组成的数组

index处删除,index右面的元素集体左移

index处添加,iindex以及右面的元素集体右移

arr.join(str) 合成的字符串=(arr.length)个数组元素+(arr.length-1)个str
arr.fill(数据)

数据是基本类型:所有数组元素等于相同的值

数据是对象:所有数组元素指向同一对象

核心用法:new Array(n).fill(0),填充空item

arr.toString()

arr=[1,2]

arr.toString()<=>arr.join(',')<=>1,2

arr.valueOf()

arr=[1,2]

arr.valueOf()==arr<=>[1,2]
arr.every(item=>{})

所有回调函数返回true,结果返回true

有一个不返回true,结果返回false

arr.some(item=>{})

有回调函数返回true,结果返回true

全都没返回true,结果返回false

arr.includes(item)

arr数组有item,结果返回true

arr数组无item,结果返回false

arr.find(item=>{})

有回调函数返回true,结果返回本次回调传入的item

全都的回调都没返回true,结果返回undefined

arr.sort((el1,el2)=>{return num=el1-el2})

  • 数组中的位置:el1在el2的右边
  • num>=0,el1和el2的位置不变
  • num<0,el1和el2交换位置

String原型方法

不改变原字符串

contact、repeat、slice、from

subString、trim、split

toLowerCase、toUpperCase

match、matchAll

replace、replaceAll

search

查找||判断

charAt、indexOf、includes

startsWith、endsWith

查找||判断参数

参数1:查找||判断的数据

参数2:查找||判断的起始索引

str.substring(beginIndex,endIndex)

str.slice(beginIndex,endIndex)

前闭后开
str.indexOf(字符,beginIndex)

从左向右检索[beginIndex,str.length-1]

======>

str.lastIndexOf(字符,beginIndex)

从右向左检索[0,beginIndex]

<======

str.split(分隔符字符串)str中有n个分割符字符串,会产生长度为n+1的数组
str.charAt(index)

获取指定位置的字符

超出str范围,会返回空字符串

str.charCodeAt(index)

获取指定位置字符的ascii码

超出str范围,返回NaN

strA.search(regex)

只有非全局模式

匹配成功,返回首个满足条件的子串的索引

匹配失败,返回-1

strA.match(regex)

非全局模式

匹配成功,返回首个满足条件的子串详细信息

        result[0]=匹配结果

        result.index=匹配结果起始索引

        result.input=参与的匹配字符

        result.groups=匹配结果分组

匹配失败,返回null

全局模式

匹配成功,返回全部满足条件的子串

匹配失败,返回null

strA.replace(regex,strb)

非全局模式

返回替换后的strA,首个满足条件的子串stra被替换为strb

全局模式

返回替换后的strA,所有满足条件的子串stra被替换为strb

strA.matchAll(regex)

只有全局模式

匹配成功,返回全部满足条件的子串详细信息

strA.replaceAll(

        regex||subStr,

        strb||(result,index,input,groups)

)

只有全局模式

返回替换后的strA,所有满足条件的子串stra被替换为strb

转义字符

  • \n:换行符
  • \t:制表符
  • \r:回车符
  • \":双引号
  • \':单引号
  • \\:反斜杠
  • \b:退格符
  • \f:换页符
  • \v:垂直制表符

Number函数方法

  • Number.isInteger(num):判断num是整数
  • Number.isNaN(数据):判断是NaN
  • NaN==NaN:结果是false
  • "_"分隔数字:100100100===100_100_100

Number原型方法

  • num.toString(n进制):十进制数转成n进制字符串
  • num.toPrecision(n):保留n位数
  • num.toFixed(n):保留n位小数
  • num.toExponential(n):转换成科学计数法格式的字符串,并保留n为小数
  • num.toLocaleString():转换成特定格式的字符串;默认转换成含有逗号的字符串

Symbol对象

  • 作用:创建唯一的、不可改变的符号

Symbol扩展普通对象

const o={}
用于 for of迭代
o.[Symbol.iterator]=function* (){
    for(const key of Object.keys(this)){
           yield [key,this[key]]
    }
}

用于 o.toString() => "[object o]"
o.[Symbol.toStringTag]="o"

用于类型强转(o)
o.[Symbol.toPrimitive]=function(type){
    type === "number"&&return 10
    type === "string"&&return "hello"
    return true    
}

用于 [] instanceof o
o.[Symbol.hasInstance]

用于字符串的正则
o.[Symbol.match]
o.[Symbol.matchAll]
o.[Symbol.replace]
o.[Symbol.search]

用于字符串的split
o.[Symbol.split]

用于数组的contact
o.[Symbol.isContatSpreadable]

Math对象

  • Math.ceil(num):num向上取整
  • Math.floor(num):num向下取整
  • Math.round(num):四舍五入
  • Math.max(a,b,...,c):求最大值
  • Math.min(a,b,...,c):求最小值
  • Math.abs(num):绝对值
  • Math.sqrt(num):num的平方根
  • Math.pow(x,y):x的y次幂
  • Math.randow():[0,1)之间的随机数
  • Math.PI:计算到精度最大,3.14……

JavaScript采用IEEE 754双精度浮点数(64位)

  • 64位分成三个部分:符号位、指数位和尾数位

JSON对象

stringify

数字类型、字符串类型、布尔类型=>字符串类型

null、NaN=>字符串"null"

undefined、函数=>undefined

集合=>{}

对象和数组=>JSON格式

parseJSON字符串转成对象

Date原型方法

  • const date new Date():获取当前时间
  • data.getTime():获取时间戳
  • date.getFullYear():获取年份
  • date.getMonth():获取月份(0是1月,11是12月)
  • date.getDate():获取日期
  • date.getHours():获取小时
  • date.getMinutes():获取分钟
  • date.getSeconds():获取秒钟
  • date.getDay():获取星期几(0是星期日,1是星期一)

ISO 8601格式

  1. “YYYY”:年份
  2. “MM”:月份
  3. “DD”:日期
  4. “hh” 12小时制
  5. “HH” 24小时制
  6. “mm”:2位数分钟
  7. “ss”:2位数秒钟
  8. “sss”:3位数毫秒
  9. “Z”:时区偏移量表示,例如+08:00表示东八区,-05:00表示西五区

moment库

import moment from 'moment'

//获取当前时间的指定格式:23/08/30 16:20:15
moment().format('YY/MM/DD HH:mm:ss')

//获取指定时间的指定格式
moment("23/08/30 16:20:15").format('YYYY-MM-DD');

const seconds=58.666333                                  
const duration = moment.duration(seconds, 'seconds');  
const t=duration.asMilliseconds()
moment.utc(t).format('HH:mm:ss');       //00:00:58

// 获取去年的日期
let lastYearDate = moment().subtract(1, 'year').format('YYYY-MM-DD');

//获取两天前的时间戳
moment().subtract(2,'day').valueOf()

RegExp正则对象

声明

构造函数:new RegExp(pattern,modifiers)

简写:/pattern/modifiers

regex.test(strA)匹配strA[regex.lastIndex]后面部分,lastIndex初始值为0

非全局模式

匹配成功:返回true,regex.lastIndex=0

匹配失败:返回false,regex.lastIndex=0

全局模式

匹配成功:返回true,regex.lastIndex=stra后一位

匹配失败:返回false,regex.lastIndex=0

regex.exec(strA)匹配strA[regex.lastIndex]后面部分,lastIndex初始值为0

非全局模式

匹配成功:返回匹配字符串stra详细信息,regex.lastIndex=0

匹配失败:返回null,regex.lastIndex=0

全局模式

匹配成功:返回匹配字符串stra详细信息,regex.lastIndex=stra后一位

匹配失败:返回null,regex.lastIndex=0

全局属性方法

  • parseInt(str,n进制=10):n进制字符串str转成十进制整数,尽量将字符串解析成整数
  • parseFloat(str):字符串str转换成十进制浮点数,尽量将字符串解析成浮点数

Node内置对象

process对象

  • process.argv:命令行参数
  • process.cwd():运行命令的目录
  • process.env:系统环境变量
  • process.pid:进程ID
  • process.platform:操作系统平台
  • process.stdout.write(字符串):标准输出流;console.log底层就是使用stdout.write()
  • process.stdin.on('data',(控制台输入数据)=>{}):标准输入流
console.log(process.argv)

//运行指令
PS D:\> node .\test.js -1 -2 -3   
['D:\\proSofts\\nodejs\\node.exe','D:\\test.js','-1','-2','-3']

Java的System对象

  • 标准输入流:
  1. BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  2. String inputString = br.readLine();
  • 标准输出流:System.out.println()
  • 命令行目录:System.getProperty("user.dir")

path模块

resolve(path1,

    path2,...arg

)

参数中有绝对路径:

    保留最后一个绝对路径PathABS,PathABS与后面的相对路径依次连接

参数中没有绝对路径:

    绝对路径__dirname,与参数中的相对路径依次连接

join(path1,

    path2,...arg

)

"/xxx"、"xxx"、"./xxx"将转换为"/xxx"

"../xxx"会把父级路由删除,如:../aaa/bbb../ccc=>../aaa/ccc

dirname(path)获取文件目录

basename(path)

获取文件名
relative(from,to)from到to的相对路径
path.posix

path模块路径分隔符,是反斜杠还是正斜杠,默认根据操作系统而定

Windows系统的路径分隔是反斜杠

使用path.posix,路径分隔符将强制采用正斜杠

event模块

注册事件myEmitter.on(事件名, callback)
myEmitter.addListener(事件名, callback)
myEmitter.once(事件名, callback)
触发事件myEmitter.emit(事件名)
取消注册myEmitter.removeListener(事件名, callback)
myEmitter.removeAllListeners(事件名)
 

const eventNames = myEmitter.eventNames()

const listeners = myEmitter.listeners(事件名)

child_process

  • exec:创建新的shell,运行程序;并一次性收到程序输出结果
  • execFile:创建系统级子进程,运行程序;并一次性收到程序输出结果
  • spawn: 创建系统级子进程,运行程序;以流的方式,实时收到程序输出结果
  • fork: 创建nodejs级子进程,运行程序;以流的方式,实时收到程序输出结果

Proxy对象

代理的精髓

在读取变量、设置变量、调用方法之前,执行一段代码

单层代理

6b9ea30b821249dd85a82fd680c523de.jpeg

2489d24fae7a4cc698c97e0470c88957.jpeg

  • 操作studentMessage不会触发get,set方法
  • 操作studentMessageProxy才会触发get,set方法。

f13e03cd1c024570849e5a6fac5e3cf1.jpeg

let studentMessage={
    name:'张三',
    age:34
}
let studentMessageProxy=new Proxy(studentMessage,{
    get(target,key){
        console.log('target',target)
        console.log('key',key)
        return target[key]
    },
    set(target,key,newVal){
        console.log('target',target)
        console.log('key',key)
        console.log('newVal',newVal)
        target[key]=newVal
    }
})
studentMessageProxy.age
studentMessageProxy.age=45


let arr=['小明','男',34]
let arrProxy=new Proxy(arr,{
    get(target,key){
        console.log('target',target)
        console.log('key',key)
        return target[key]
    },
    set(target,key,newVal){
        console.log('target',target)
        console.log('key',key)
        console.log('newVal',newVal)
        target[key]=newVal
    }
})

arrProxy[0]
arrProxy[0]='李四'


PS C:\Users\Administrator\Desktop\测试\node+浏览器环境测试\proxy的使用> node .\proxy4.js
target { name: '张三', age: 34 }
key age
target { name: '张三', age: 34 }
key age
newVal 45
target [ '小明', '男', 34 ]
key 0
target [ '小明', '男', 34 ]
key 0
newVal 李四

初始化

  • let proxyData = new Proxy(data, {get(target, key, receiver) {}})
  • Object.setPrototypeOf(obj, proxyData)

target和receiver的指向

  • target指向data
  • proxyData访问data属性,receiver指向proxyData
  • obj访问data属性,receiver指向obj

 多层代理

3911b7f9d9164d71a5b467589176c9fc.jpeg

d0173caecdc2468ea5a6b41e42523fc5.jpeg

54503e6461bb47a096abfcab74177cad.jpeg

 递归实现思路

  1. 实现对family、friend 的数据劫持
  2. 实现对 data 的数据劫持
function getProxyData(data){
    if(typeof data!=='object'){
        return data
    }

    if(Array.isArray(data)){
        for(let i=0;i<data.length;i++){
            data[i]=getProxyData(data[i])
        }
    }
    else{
        let dataKeys=Object.keys(data)
        for(let i=0;i<dataKeys.length;i++){
            data[dataKeys[i]]=getProxyData(data[dataKeys[i]])
        }
    }

    data=new Proxy(data,{
        get(target,key){
            console.log(target)
            console.log(key)
            return target[key]
        },
        set(target,key,newVal){
            console.log(target)
            console.log(key)
            console.log(newVal)
            target[key]=newVal
        }
    })
    return data
}

let studentMessage={
    name:'张三',
    age:34,
    parents:{
        mother:'李四',
        father:'王五'
    },
    friends:['Tom','jack']
}
studentMessage=getProxyData(studentMessage)
console.log(studentMessage)
studentMessage.age=56
studentMessage.parents.mother='阿娇'
studentMessage.friends[0]='阿坤'



PS C:\Users\Administrator\Desktop\简单测试\proxy的使用> node .\proxy.js
//打印studentMessage
{
  name: '张三',
  age: 34,
  parents: { mother: '李四', father: '王五' },
  friends: [ 'Tom', 'jack' ]
}

//修改studentMessage.age
{
  name: '张三',
  age: 34,
  parents: { mother: '李四', father: '王五' },
  friends: [ 'Tom', 'jack' ]
}
age
56

//修改studentMessage.parents.mother
{
  name: '张三',
  age: 56,
  parents: { mother: '李四', father: '王五' },
  friends: [ 'Tom', 'jack' ]
}
parents
{ mother: '李四', father: '王五' }
mother
阿娇

//修改stuentMessage.friends[0]
{
  name: '张三',
  age: 56,
  parents: { mother: '阿娇', father: '王五' },
  friends: [ 'Tom', 'jack' ]
}
friends
[ 'Tom', 'jack' ]
0
阿坤

C++代码生成Node原生模块

配置环境

  1. 安装VS Installer
  2. 安装VS Community
  3. 安装C++桌面开发环境
  4. 安装python
  5. 配置环境变量
  6. npm i -g node-gyp

编写C++代码

Test.cpp

#include <node.h>
#include <iostream>

void MyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
	std::cout << "Hello, world!" << std::endl;
}
void Init(v8::Local<v8::Object> exports) {
	NODE_SET_METHOD(exports, "myFunction", MyFunction);
}
NODE_MODULE(addon, Init)

编写配置文件

binding.gyp

{
  "targets": [
    {
      "target_name": "addon",
      "sources": ["Test.cpp"]
    }
  ]
}

编写运行代码

Test.js

const addon = require('./build/Release/addon');
addon.myFunction();

构建

  1. node-gyp configure
  2. node-gyp build

目录结构

> build

> binding.gyp

> Test.cpp

> Test.js

正则

正则对象regex与字符串A的关系

  • 字符串A中寻找,满足正则对象regex规则的首个子串
  • 字符串A中寻找,满足正则对象regex规则的所有子串

普通字符

  • [2sJ70]:匹配[]中的任意字符
  • [a-z]:匹配a到z中,任意字符
  • [a-z0-9]:匹配a到z,0到9中,任意字符
  • \d:数字
  • \s:空白字符
  • .:任意字符

需要转义的字符

^ ,$, {}, [],(),?,+,*,.,|,\ 

限定次数符

  • {n}:需要匹配n次
  • {n,}:需要匹配至少n次
  • {n,m}:需要匹配至少n,至多m次
  • ?:需要匹配0或1次
  • +:需要匹配至少1次
  • *:需要匹配0次或至少1次
  • .*、.+:默认开启贪婪模式
  • .*?、.+?:关闭贪婪模式

定位符

  • ^:匹配字符串A的首部
  • $:匹配字符串A的尾部

选择符和分组符

  • ():分组符,每一个分组的值都会被保存到捕获组里。
  • |:在()号范围内|号左右的正则表达式满足一个,匹配成功

举例:

正则表达式:/(a|B)(s|[123])/

字符串:10as01         结果:匹配成功

字符串:10B201        结果:匹配成功

修饰符

  • g:开启全局模式
  • i:忽略大小写
  • m:多行匹配

集合

全面的Java

0feb5b23b1ab4f6f92250352aadda6df.jpeg

  • Array:长度固定、类型固定、元素可以重复
  • List:长度不固定、类型不固定、元素可以重复
  • Set:长度不固定、类型不固定、元素去重
  • Map:长度不固定、类型不固定、key值去重
  • 实例对象:长度固定、类型固定、属性值去重
  • 迭代器:iterator,enumeration
  • 通过包装类实现存储基本数据类型
  • Java8提供了Stream API,使得Java集合拥有和JS数组类似的方法

for迭代器

for(类型 元素:数组){}
数组.forEach(元素->{})

for(类型 元素:单列集合){}
单列集合.forEach(元素->{})

map.forEach((value,key)->{})
map.keySet()
map.values()
map.entrySet()

精炼的JS

  • 数组=Array+List:长度不固定、类型不固定、元素可以重复
  • Set:长度不固定、类型不固定、元素去重
  • Map:长度不固定、类型不固定、key值去重
  • 实例对象:长度不固定、类型不固定、属性值去重、属性值是字符串或Symbol
let obj={
    key1:value1,     //key1当成字符串解析
    "key2":value2,   //key2当成字符串解析
    [key3]:value3    //key3当成变量解析
}
 Set集合Map集合 

add

set

delete

clear

delete

clear

/replace

has

size

has、get

size

 

Array.from

Array.from

遍历方式 

  • for of:遍历对象的Symbol.iterator属性
  • for in:遍历对象的可枚举属性
  • for( ...; ...; ... ):依据索引遍历对象
  • forEach:见JavaScript1底层封装讲解
数组

for(let 元素 of 数组){}

数组.forEach(元素=>{})

for(let 索引 in 数组){}

Set集合

for(let 元素 of set集合)

set集合.forEach(元素=>{})

对象

Object.keys(对象)

Object.values(对象)

Object.entries(对象)

for(let key in 对象){}

for(let yield的值 of 对象){}

Map集合

Map集合.forEach((value,key)=>{})

map.keys()、map.values()、map.entries()

IO流/File

IO流概述

  • 程序的内存当成人脑
  • 外部的数据通过输入流(inputstream)进入人脑
  • 人脑的数据通过输出流(outputstream)进入外部
  • 人阅读(read)从外界获得数据
  • 人书写(write)向外界传递数据
 IO流
Js内置模块fs
Java

字节流(InputStream、OutputStream)

字符流(Reader、Writer)

fs模块

一次性读入

fs.readFile('文件路径','utf8',(err,数据)=>{})

let 数据=fs.readFileSync('文件路径','utf8')
流式读入

const stream=fs.createReadStream('文件路径',{encoding:"utf8"})

stream.on("data",(chunk)=>{...})

stream.on('end',()=>{...})

stream.on('error',(err)=>{...})

覆盖式写出

fs.writeFile(文件路径, 数据, 'utf8', (err)=>{})

fs.writeFileSync(文件路径, 数据, 'utf8')
追加式写出

fs.appendFile(文件路径, 数据, 'utf8', (err)=>{})

fs.appendFileSync(文件路径, 数据, 'utf8')
流式写出

const stream=fs.createWriteStream("文件名",{encoding:"utf8"})

stream.on("finish",()=>{...})

stream.on('error',(err)=>{...})

stream.wirte("xxx")

stream.wirte("yyy")

stream.end()

创建目录

fs.mkdir(目录路径, (err)=>{})

fs.mkdirSync(目录路径)

删除文件

fs.unlink(文件路径, (err)=>{})

fs.unlinkSync(文件路径)

删除目录

fs.rmdir(目录路径,(err)=>{})

fs.rmdirSync(目录路径)

重命名

fs.rename(旧路径名称, 新路径名称, (err)=>{})

fs.renameSync(旧路径名称, 新路径名称)

目录内容

fs.readdir(目录路径,(err,文件&&目录数组)=>{})

let 文件&&目录数组=fs.readdirSync(目录路径)

文件||目录信息

fs.statSync(文件||目录信息)

采用相对路径时,是相对于nodejs进程的运行目录 

readline模块

import readline from 'readline'

const rl = readline.createInterface({
  input: 输入流,
  output: 输出流,
  prompt: '输入提示符'
});

rl.on('line', (line) => {...})
rl.on('close', () => {...})

Socket通信

TCP

服务端监听

客户端连接

客户端与服务端通信

双方断开连接

UDP

双方开启监听

无需建立连接

发送方想发就发,接收方能接就接

 

fb52da815082424b8efb3027a26243eb.jpeg

Node&dgram&UDP

UDP端口1

import dgram from 'dgram'

const server = dgram.createSocket('udp4');
server.on('message', (msg, rinfo) => {
  console.log(`Received message from ${rinfo.address}:${rinfo.port}: ${msg}`);
});
server.on('listening', () => {
  const address = server.address();
  console.log(`UDP server listening on ${address.address}:${address.port}`);
});

const PORT = 3000;
server.bind(PORT);

UDP端口2

import dgram from 'dgram'

const client = dgram.createSocket('udp4');
const message = Buffer.from('Hello, server!');
client.send(message, 0, message.length, 3000, 'localhost', (err) => {
  client.close();
});

Node&net&TCP

服务端

import net from 'net');

const server = net.createServer((socket) => {
  console.log('New client connected.');

  socket.on('data', (data) => {
    console.log(`Received data: ${data}`);
    socket.write('Server response');
  });

  socket.on('end', () => {
    console.log('Client disconnected.');
  });
});

const PORT = 3000;
server.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});

客户端

import net from 'net'

const client = net.createConnection({ port: 3000 }, () => {
  console.log('Connected to server.');
  client.write('Hello server');
});

client.on('data', (data) => {
  console.log(`Received data: ${data}`);
  client.end();
});

client.on('end', () => {
  console.log('Disconnected from server.');
});

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stealPigs-youth

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值