微信号:fed-talk

介绍:公众号开通于2016年,内容起于前端而不止于前端.

stdin and stdout which it's ?

2018-06-17 00:08 五溪

“基础不牢,还真是办事不牢”


最近写了几个C函数,来处理项目中一个Desktop跨应用的进程通信,被32-bit,LE(BE)折磨了很久,stdin and stdout 看起来是一个很简单的标准输入输出,但是处理的过程中,却遇到了很大的障碍,因为历史问题,一个bytes的长度,需要将消息的位置移动4个byte存储消息的长度,先发送给对方,告诉对方我即将发送一个多少长度的byte,反之解析也是亦然。


这其实是一个很小的问题,好在经过不懈努力,终于解决了它。


Node.js Stdin and Stdout


对应Node.js实现相同的问题,那就要简单了很多,process对象是一个Global全局对象,这意味着使用它并不需要导入,同时它还是一个EventEmitter的实例,相应的事件处理,也非常的简单。process对象包含了Node.js运行时环境的方方面面,包括stdin,stdout也是使用process对象来处理(其实它还有一个stderr标准错误流)。


做为标准输出流的stdout是一个指向标准输出流的可写入的Writable Stream,我们经常使用的console.log就是使用process.stdout来实现的。既然它属于Writable Stream那么也意味着stdout存在着Stream抽象类的方法,比如write,setEncoding,end等等。


(说明:Stream模块是一个抽象类,https://nodejs.org/dist/latest-v8.x/docs/api/stream.html)


process.stdin.pipe(process.stdout);


做为标准输入流的stdin是一个指向标准输入流的可读的Readable Stream,目前新的API与旧版已经有了不同:


process.stdin.setEncoding('utf8');

process.stdin.on('readable', () => {  const chunk = process.stdin.read();  if (chunk !== null) {    process.stdout.write(`data: ${chunk}`);  }
});

process.stdin.on('end', () => {  process.stdout.write('end');
});


(注明:新版中的实现并未像旧版那样,标准输入流默认是暂停 (pause) 的,必须要调用 process.stdin.resume() 来恢复 (resume) 接收,而是使用了一个事件,然后调用read来读取。)


我们可以非常形象的将stdin 和 stdout 用一张图来画出来,它其实就是一个Pipe(管道),一边连着stdin,一边连着stdout,对于Pipe,如果你处理过读取大文件,视频等,就很能理解它了。

其实通过Node.js能非常简单的处理上述,我遇到的那个小问题,只不过在解决这个问题的过程中,我们还需要面对一下历史原因的问题,那就是BE and LE,所谓的字节序,也就是字节的顺序,它指的是多字节数据在内存中存放的顺序,这里面的历史如果有兴趣的话,可以自行Google,两大CPU流派,我只想说一下,为什么我们要关注到这个,因为在处理字节的时候,特别是使用了stdout.write写入bytes时,不同的字节序,很有可能意味着你的程序并不能正常的发送消息。


不过,好在目前的状况是有了两个比较目前的使用状况:


  • 网络字节序:TCP/IP各层协议将字节序定义为 Big Endian,因此TCP/IP协议中使用的字节序是大端序。

  • 主机字节序:整数在内存中存储的顺序,现在 Little Endian 比较普遍。(不同的 CPU 有不同的字节序)


且默认在本地内存中使用LE吧,我的那个小问题处理,也是使用的LE。




长按二维码关注公众号:

你也可以关注我的新浪微博,搜索i_icepy,很期待和大家交流

 
象尘说 更多文章 Chat推荐:成长-浅谈从前端小工到工程师的三年转换 搭建 Private NPM Chat推荐:从0到1快速开发钉钉微应用 Go HTTP Go JSON
猜您喜欢 SHELL编程之常用技巧 Python基础教程16:元组 不懂技术的人不要对懂技术的人说这很容易实现 夜归 代码传奇 | 身价10亿的程序员 雷军当年也为他打工——WPS之父 求伯君