Server-Sent Events 教程

服务器向浏览器推送信息,除了 WebSocket,还有一种方法:Server-Sent Events(以下简称 SSE)。本文介绍它的用法。

一、SSE 的本质

严格地说,HTTP 协议无法做到服务器主动推送信息。但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息(streaming)。

也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。本质上,这种通信就是以流信息的方式,完成一次用时很长的下载。

SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 HTTP 协议,目前除了 IE/Edge,其他浏览器都支持。

二、SSE 的特点

SSE 与 WebSocket 作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。

总体来说,WebSocket 更强大和灵活。因为它是全双工通道,可以双向通信;SSE 是单向通道,只能服务器向浏览器发送,因为流信息本质上就是下载。如果浏览器向服务器发送信息,就变成了另一次 HTTP 请求。

但是,SSE 也有自己的优点。

  • SSE 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。
  • SSE 属于轻量级,使用简单;WebSocket 协议相对复杂。
  • SSE 默认支持断线重连,WebSocket 需要自己实现。
  • SSE 一般只用来传送文本,二进制数据需要编码后传送,WebSocket 默认支持传送二进制数据。
  • SSE 支持自定义发送的消息类型。

因此,两者各有特点,适合不同的场合。

三、客户端 API

3.1 EventSource 对象

SSE 的客户端 API 部署在EventSource对象上。下面的代码可以检测浏览器是否支持 SSE。


if ('EventSource' in window) {
  // ...
}

使用 SSE 时,浏览器首先生成一个EventSource实例,向服务器发起连接。


var source = new EventSource(url);

上面的url可以与当前网址同域,也可以跨域。跨域时,可以指定第二个参数,打开withCredentials属性,表示是否一起发送 Cookie。


var source = new EventSource(url, { withCredentials: true });

EventSource实例的readyState属性,表明连接的当前状态。该属性只读,可以取以下值。

  • 0:相当于常量EventSource.CONNECTING,表示连接还未建立,或者断线正在重连。
  • 1:相当于常量EventSource.OPEN,表示连接已经建立,可以接受数据。
  • 2:相当于常量EventSource.CLOSED,表示连接已断,且不会重连。

3.2 基本用法

连接一旦建立,就会触发open事件,可以在onopen属性定义回调函数。


source.onopen = function (event) {
  // ...
};

// 另一种写法
source.addEventListener('open', function (event) {
  // ...
}, false);

客户端收到服务器发来的数据,就会触发message事件,可以在onmessage属性的回调函数。


source.onmessage = function (event) {
  var data = event.data;
  // handle message
};

// 另一种写法
source.addEventListener('message', function (event) {
  var data = event.data;
  // handle message
}, false);

上面代码中,事件对象的data属性就是服务器端传回的数据(文本格式)。

如果发生通信错误(比如连接中断),就会触发error事件,可以在onerror属性定义回调函数。


source.onerror = function (event) {
  // handle error event
};

// 另一种写法
source.addEventListener('error', function (event) {
  // handle error event
}, false);

close方法用于关闭 SSE 连接。


source.close();

3.3 自定义事件

默认情况下,服务器发来的数据,总是触发浏览器EventSource实例的message事件。开发者还可以自定义 SSE 事件,这种情况下,发送回来的数据不会触发message事件。


source.addEventListener('foo', function (event) {
  var data = event.data;
  // handle message
}, false);

上面代码中,浏览器对 SSE 的foo事件进行监听。如何实现服务器发送foo事件,请看下文。

四、服务器实现

4.1 数据格式

服务器向浏览器发送的 SSE 数据,必须是 UTF-8 编码的文本,具有如下的 HTTP 头信息。


Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

上面三行之中,第一行的Content-Type必须指定 MIME 类型为event-steam

每一次发送的信息,由若干个message组成,每个message之间用\n\n分隔。每个message内部由若干行组成,每一行都是如下格式。


[field]: value\n

上面的field可以取四个值。

  • data
  • event
  • id
  • retry

此外,还可以有冒号开头的行,表示注释。通常,服务器每隔一段时间就会向浏览器发送一个注释,保持连接不中断。


: This is a comment

下面是一个例子。


: this is a test stream\n\n

data: some text\n\n

data: another message\n
data: with two lines \n\n

4.2 data 字段

数据内容用data字段表示。


data:  message\n\n

如果数据很长,可以分成多行,最后一行用\n\n结尾,前面行都用\n结尾。


data: begin message\n
data: continue message\n\n

下面是一个发送 JSON 数据的例子。


data: {\n
data: "foo": "bar",\n
data: "baz", 555\n
data: }\n\n

4.3 id 字段

数据标识符用id字段表示,相当于每一条数据的编号。


id: msg1\n
data: message\n\n

浏览器用lastEventId属性读取这个值。一旦连接断线,浏览器会发送一个 HTTP 头,里面包含一个特殊的Last-Event-ID头信息,将这个值发送回来,用来帮助服务器端重建连接。因此,这个头信息可以被视为一种同步机制。

4.4 event 字段

event字段表示自定义的事件类型,默认是message事件。浏览器可以用addEventListener()监听该事件。


event: foo\n
data: a foo event\n\n

data: an unnamed event\n\n

event: bar\n
data: a bar event\n\n

上面的代码创造了三条信息。第一条的名字是foo,触发浏览器的foo事件;第二条未取名,表示默认类型,触发浏览器的message事件;第三条是bar,触发浏览器的bar事件。

下面是另一个例子。


event: userconnect
data: {"username": "bobby", "time": "02:33:48"}

event: usermessage
data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}

event: userdisconnect
data: {"username": "bobby", "time": "02:34:23"}

event: usermessage
data: {"username": "sean", "time": "02:34:36", "text": "Bye, bobby."}

4.5 retry 字段

服务器可以用retry字段,指定浏览器重新发起连接的时间间隔。


retry: 10000\n

两种情况会导致浏览器重新发起连接:一种是时间间隔到期,二是由于网络错误等原因,导致连接出错。

五、Node 服务器实例

SSE 要求服务器与浏览器保持连接。对于不同的服务器软件来说,所消耗的资源是不一样的。Apache 服务器,每个连接就是一个线程,如果要维持大量连接,势必要消耗大量资源。Node 则是所有连接都使用同一个线程,因此消耗的资源会小得多,但是这要求每个连接不能包含很耗时的操作,比如磁盘的 IO 读写。

下面是 Node 的 SSE 服务器实例


var http = require("http");

http.createServer(function (req, res) {
  var fileName = "." + req.url;

  if (fileName === "./stream") {
    res.writeHead(200, {
      "Content-Type":"text/event-stream",
      "Cache-Control":"no-cache",
      "Connection":"keep-alive",
      "Access-Control-Allow-Origin": '*',
    });
    res.write("retry: 10000\n");
    res.write("event: connecttime\n");
    res.write("data: " + (new Date()) + "\n\n");
    res.write("data: " + (new Date()) + "\n\n");

    interval = setInterval(function () {
      res.write("data: " + (new Date()) + "\n\n");
    }, 1000);

    req.connection.addListener("close", function () {
      clearInterval(interval);
    }, false);
  }
}).listen(8844, "127.0.0.1");

请将上面的代码保存为server.js,然后执行下面的命令。


$ node server.js

上面的命令会在本机的8844端口,打开一个 HTTP 服务。

然后,打开这个网页,查看客户端代码并运行。

六、参考链接

(完)

文档信息

WebSocket 教程

WebSocket 是一种网络通信协议,很多高级功能都需要它。

本文介绍 WebSocket 协议的使用方法。

一、为什么需要 WebSocket?

初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。

举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。

这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用“轮询”:每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。

轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。

二、简介

WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。

它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

其他特点包括:

(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。


ws://example.com:80/some/path

三、客户端的简单示例

WebSocket 的用法相当简单。

下面是一个网页脚本的例子(点击这里看运行结果),基本上一眼就能明白。


var ws = new WebSocket("wss://echo.websocket.org");

ws.onopen = function(evt) { 
  console.log("Connection open ..."); 
  ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt) {
  console.log( "Received Message: " + evt.data);
  ws.close();
};

ws.onclose = function(evt) {
  console.log("Connection closed.");
};      

四、客户端的 API

WebSocket 客户端的 API 如下。

4.1 WebSocket 构造函数

WebSocket 对象作为一个构造函数,用于新建 WebSocket 实例。


var ws = new WebSocket('ws://localhost:8080');

执行上面语句之后,客户端就会与服务器进行连接。

实例对象的所有属性和方法清单,参见这里

4.2 webSocket.readyState

readyState属性返回实例对象的当前状态,共有四种。

  • CONNECTING:值为0,表示正在连接。
  • OPEN:值为1,表示连接成功,可以通信了。
  • CLOSING:值为2,表示连接正在关闭。
  • CLOSED:值为3,表示连接已经关闭,或者打开连接失败。

下面是一个示例。


switch (ws.readyState) {
  case WebSocket.CONNECTING:
    // do something
    break;
  case WebSocket.OPEN:
    // do something
    break;
  case WebSocket.CLOSING:
    // do something
    break;
  case WebSocket.CLOSED:
    // do something
    break;
  default:
    // this never happens
    break;
}

4.3 webSocket.onopen

实例对象的onopen属性,用于指定连接成功后的回调函数。


ws.onopen = function () {
  ws.send('Hello Server!');
}

如果要指定多个回调函数,可以使用addEventListener方法。


ws.addEventListener('open', function (event) {
  ws.send('Hello Server!');
});

4.4 webSocket.onclose

实例对象的onclose属性,用于指定连接关闭后的回调函数。


ws.onclose = function(event) {
  var code = event.code;
  var reason = event.reason;
  var wasClean = event.wasClean;
  // handle close event
};

ws.addEventListener("close", function(event) {
  var code = event.code;
  var reason = event.reason;
  var wasClean = event.wasClean;
  // handle close event
});

4.5 webSocket.onmessage

实例对象的onmessage属性,用于指定收到服务器数据后的回调函数。


ws.onmessage = function(event) {
  var data = event.data;
  // 处理数据
};

ws.addEventListener("message", function(event) {
  var data = event.data;
  // 处理数据
});

注意,服务器数据可能是文本,也可能是二进制数据(blob对象或Arraybuffer对象)。


ws.onmessage = function(event){
  if(typeof event.data === String) {
    console.log("Received data string");
  }

  if(event.data instanceof ArrayBuffer){
    var buffer = event.data;
    console.log("Received arraybuffer");
  }
}

除了动态判断收到的数据类型,也可以使用binaryType属性,显式指定收到的二进制数据类型。


// 收到的是 blob 数据
ws.binaryType = "blob";
ws.onmessage = function(e) {
  console.log(e.data.size);
};

// 收到的是 ArrayBuffer 数据
ws.binaryType = "arraybuffer";
ws.onmessage = function(e) {
  console.log(e.data.byteLength);
};

4.6 webSocket.send()

实例对象的send()方法用于向服务器发送数据。

发送文本的例子。


ws.send('your message');

发送 Blob 对象的例子。


var file = document
  .querySelector('input[type="file"]')
  .files[0];
ws.send(file);

发送 ArrayBuffer 对象的例子。


// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i 

4.7 webSocket.bufferedAmount

实例对象的bufferedAmount属性,表示还有多少字节的二进制数据没有发送出去。它可以用来判断发送是否结束。


var data = new ArrayBuffer(10000000);
socket.send(data);

if (socket.bufferedAmount === 0) {
  // 发送完毕
} else {
  // 发送还没结束
}

4.8 webSocket.onerror

实例对象的onerror属性,用于指定报错时的回调函数。


socket.onerror = function(event) {
  // handle error event
};

socket.addEventListener("error", function(event) {
  // handle error event
});

五、服务端的实现

WebSocket 服务器的实现,可以查看维基百科的列表

常用的 Node 实现有以下三种。

具体的用法请查看它们的文档,这里不详细介绍了。

六、WebSocketd

下面,我要推荐一款非常特别的 WebSocket 服务器:Websocketd

它的最大特点,就是后台脚本不限语言,标准输入(stdin)就是 WebSocket 的输入,标准输出(stdout)就是 WebSocket 的输出。

举例来说,下面是一个 Bash 脚本counter.sh


#!/bin/bash

echo 1
sleep 1

echo 2
sleep 1

echo 3

命令行下运行这个脚本,会输出1、2、3,每个值之间间隔1秒。


$ bash ./counter.sh
1
2
3

现在,启动websocketd,指定这个脚本作为服务。


$ websocketd --port=8080 bash ./counter.sh

上面的命令会启动一个 WebSocket 服务器,端口是8080。每当客户端连接这个服务器,就会执行counter.sh脚本,并将它的输出推送给客户端。


var ws = new WebSocket('ws://localhost:8080/');

ws.onmessage = function(event) {
  console.log(event.data);
};

上面是客户端的 JavaScript 代码,运行之后会在控制台依次输出1、2、3。

有了它,就可以很方便地将命令行的输出,发给浏览器。


$ websocketd --port=8080 ls

上面的命令会执行ls命令,从而将当前目录的内容,发给浏览器。使用这种方式实时监控服务器,简直是轻而易举(代码)。

更多的用法可以参考官方示例

websocketd 的实质,就是命令行的 WebSocket 代理。只要命令行可以执行的程序,都可以通过它与浏览器进行 WebSocket 通信。下面是一个 Node 实现的回声服务greeter.js


process.stdin.setEncoding('utf8');

process.stdin.on('readable', function() {
  var chunk = process.stdin.read();
  if (chunk !== null) {
    process.stdout.write('data: ' + chunk);
  }
});

启动这个脚本的命令如下。


$ websocketd --port=8080 node ./greeter.js

官方仓库还有其他各种语言的例子。

七、参考链接

(完)

文档信息

素食主义者

发信人: GGGGDDDDK (我叫囫囵,枣是我吞的), 信区: Joke
标 题: 素食主义者
发信站: 水木社区 (Wed May 10 09:22:09 2017), 站内

素素和菜菜都是素食主义者。有一天,素素和另两个人在荒岛上快饿死了,于是这三个人只好商量由两个人吃另一个人。素素因为是素食主义者,就成为了被吃的那个。菜菜得到这一情况后,意识到了做素食主义者的害处,开始经常吃肉,成为了一个大胖子。后来,菜菜和另两个人乘坐热气球,途中热气球的气不多了,需要扔下去一个人,菜菜因为最重,被扔下去了。

※ 来源:·水木社区 newsmth.net·[FROM: 122.139.1.109]

以鹅为单位,各种动物的战斗力排名。 (转载)

发信人: nighthawk (83。75% 「跑马溜溜的山上」), 信区: Joke
标 题: 以鹅为单位,各种动物的战斗力排名。
发信站: 水木社区 (Fri May 5 23:24:29 2017), 站内

【 以下文字转载自 NewExpress 讨论区 】
发信人: riveryy (riveryy), 信区: NewExpress
标 题: 以鹅为单位,各种动物的战斗力排名。
发信站: 水木社区 (Fri May 5 23:08:15 2017), 站内

设成年公鹅战斗力为1鹅。
如果2只鹅能和一只田园犬旗鼓相当或同归于尽,那么田园犬是2鹅。

以下就是楼主不负责任的随意排名:

蚂蚁:0.0001鹅
蚊子:0.003鹅
毛毛虫:0.003鹅
蜗牛:0.005鹅
中型蜘蛛:0.008鹅
蚂蟥:0.01鹅
蜜蜂:0.015鹅
蜈蚣:0.02鹅
麻雀:0.03鹅
蝎子:0.05鹅
老鼠:0.05鹅
龙虾:0.1鹅
牛蛙:0.12鹅
大鲤鱼:0.15鹅
较大的螃蟹:0.18鹅
3岁以下儿童:0.2鹅
小型无毒蛇:0.2鹅
非洲牛蛙:0.22鹅
鸭子:0.25鹅
普通公鸡:0.3鹅
皮皮虾:0.35鹅
食人鱼:0.4鹅
猴子:0.4鹅
猫:0.45鹅
斗鸡:0.7鹅
10岁左右儿童:0.8鹅
猫头鹰:1.0鹅
羊:1.5鹅
田园犬:2鹅
家猪:3鹅
成年男性:4鹅
老鹰:6鹅
藏獒:10鹅
猎豹:10鹅
马蜂群:15鹅
鬣狗:20鹅
狼:25鹅
黄牛:30鹅
鳄鱼:40鹅
金钱豹:60鹅
黑熊:80鹅
熊猫:90鹅
雌狮:70鹅
雄狮:120鹅
雄东北虎:150鹅
棕熊:150鹅
非洲野牛:180鹅
河马:200鹅
大白鲨:250鹅
犀牛:300鹅
亚洲雄象:400鹅
非洲雄象:500鹅
虎鲸:600鹅
霸王龙:800鹅
狮群(10只):1200鹅
雷龙:1500鹅
蓝鲸:4000鹅
虎鲸群(10只):10000鹅

警察(持手枪):30鹅
普通陆军士兵:200鹅
坦克:5000鹅
阿帕奇:12000鹅
F16:50000鹅
F22:30万鹅
弹道导弹:500万鹅
航母:1200万鹅
核潜艇:1500万鹅
航母战斗群:6000万鹅

.
※ 修改:·riveryy 于 May 5 23:23:45 2017 修改本文·[FROM: 116.224.240.*]
※ 来源:·水木社区 http://m.newsmth.net·[FROM: 116.224.240.*]

How to make flashcards online?

In this article I’ll tell you in detail how to use Flashcard.online editor to create your own flashcards.

Have a look at this video to see how the app works:

STEP 1. Prepare images

If you’re going to make flashcards without images, just go to the next step. If you’re planning to do cards with pictures, you have to do some preparation work.

Search for free images in Google or download royalty-free stock photos and clipart images from under Creative Commons (CC0) license at websites like Pixabay.com, Pexels.com, Stocksnap.io, Unsplash.com.

Ideally, the image size for 2 cards per list is 300*400 px, for 4 per list – 250*300 px, for 8 flashcards per list – 180*220 px. Still if you don’t stick to these sizes, it’s OK that an image is just vertical. I use IrfanView Editor for fast photo cutting and rotation.

prepare images for flashcards

STEP 2. Set flashcard parameters

Go to Flashcard.online editor and set the following parameters:

  • title of your flashcard set
  • number of cards per list (2, 4, or 8)
  • type of flashcards (only text or image+text).

flashcard parameters

STEP 3. Add your content

Upload your images and add text to the flashcards. If necessary, add and remove new lists to your set.

add content to flashcards

You can create up to 5 lists in a single flashcard set.

Step 4. Save the PDF file

Once you have added everyhting, click “Save as PDF”, then “Free Download” to get the file. If you work in Chrome browser, the PDF file will be opened in a new tab. Use right-button menu to save the file to your computer. Enjoy learning with flashcards!

亲爱的,我们再也回不去了,对不对?

发信人: wangsir (joker), 信区: Joke
标 题: 亲爱的,我们再也回不去了,对不对?
发信站: 水木社区 (Tue Apr 25 17:16:05 2017), 站内

下班时接女朋友回家,我们两人一路无语,整整三十分钟竟然找不出一个话题,走到门口时,她哭了,“亲爱的,我们再也回不去了,对不对?”听完,我心都凉了,一巴掌扇了过去:“你TM又把钥匙锁屋里了?”

刚拿到驾照,一次雨后出门,车速很快把积水浪到一小伙子身上,想道歉就倒车回去,结果又溅了他一身,这下不好意思下车道歉了,踩油门速速离开,结果又溅了他一身,还记得他那句传遍整条街的怒吼,我c你大爷

讲一过去真实的事,以前和几个哥们去偷鸡吃,学电视上做 叫花鸡,直接把鸡埋地下敷上土,在上面点火半个小时,扒开后,只见鸡浑身冒着热气跑了……

再来,

小时候比较淘,挨打无数。有次老妈让我去买一斤糯米粉包汤圆,我贪吃买了半斤,其他的钱买唐僧肉和芝麻糊了。走到半路袋子又被我划破了,糯米粉都撒了,走投无路之际看到人家堆放的石灰粉,装了一些回家交差,现在我还记得我爸体贴我妈的那句话:你先歇着,我来打会…

表弟刚刚打电话来批了我一顿,原因是我帮姑姑弄了个QQ号,加了表弟好友,表弟追了姑姑一个多星期,发现这个关心他的女人是他妈

那天,走在街上和闺蜜谈论前面两位男的谁攻谁受,“蓝外套的一定是受。”那个“受”字说的太响,蓝外套直接转过头说道:“你才是受,你全家都是受!”他旁边那位对他说:“媳妇,别激动,人家说的是胖瘦的瘦!”

今天街边买烧烤的来的晚了,我给他打电话,大哥在那边说:劳资卖了这么多年烧烤从来都是自由自在,自从特么认识了你,居然让我有了上班的感觉。

逛街见一男一女吵架女:为什么要这样对我!为什么!(撕心裂肺状)男:你别这样好不好?至于吗?女(蹲在地上痛哭):你不爱我了!男:祖宗!我给你买小布丁行不行!买两根!大姨妈肚子疼别赖我!女(擦擦鼻涕眼泪):我绝对不赖你!男:你都赖了多少次了…于是两人欢乐的牵手走了,留下我纠结的站着。

熵:宇宙的终极规则

1、

有人曾经问我:”成年后,有没有书籍改变过你的世界观?”

我想了想,还真有这样的书。那时,我已经工作好几年了,偶然在图书馆翻到一本旧书《熵:一种新的世界观》(上海译文出版社,1987)。

那本书是科普著作,介绍物理学概念”熵”。中学毕业后,我再没有碰过物理学,但是没想到读完以后,我看待世界的眼光都变了。

“熵”这个概念非常简单,很容易理解,但又异常强大,可以解释很多事情。这篇文章,我就来谈谈,为什么你应该懂得熵是什么,它可能也会改变你的世界观。

2、

为了理解熵,必须讲一点物理学。

19世纪,物理学家开始认识到,世界的动力是能量,并且提出“能量守恒定律”,即能量的总和是不变的。但是,有一个现象让他们很困惑。

(上图中,单摆在两侧的最高点,势能最大,动能为零;在中间的低点,动能最大,势能为零,能量始终守恒。)

物理学家发现,能量无法百分百地转换。比如,蒸汽机使用的是热能,将其转换为推动机器的机械能。这个过程中,总是有一些热能损耗掉,无法完全转变为机械能。

(上图中,能量 E 的转换,总是会导致能量损耗 ∆E。)

一开始,物理学家以为是技术水平不高导致的,但后来发现,技术再进步,也无法将能量损耗降到零。他们就将那些在能量转换过程中浪费掉的、无法再利用的能量称为熵。

后来,这个概念被总结成了“热力学第二定律”:能量转换总是会产生熵,如果是封闭系统,所有能量最终都会变成熵。

3、

熵既然是能量,为什么无法利用?它又是怎么产生的?为什么所有能量最后都会变成熵?这些问题我想了很久。

物理学家有很多种解释,有一种我觉得最容易懂:能量转换的时候,大部分能量会转换成预先设定的状态,比如热能变成机械能、电能变成光能。但是,就像细胞突变那样,还有一部分能量会生成新的状态。这部分能量就是熵,由于状态不同,所以很难利用,除非外部注入新的能量,专门处理熵。

(上图,能量转换过程中,创造出许多新状态。)

总之,能量转换会创造出新的状态,熵就是进入这些状态的能量。

4、

现在请大家思考:状态多意味着什么?

状态多,就是可能性多,表示比较混乱;状态少,就是可能性少,相对来说就比较有秩序。因此,上面结论的另一种表达是:能量转换会让系统的混乱度增加,熵就是系统的混乱度。

(上图中,熵低则混乱度低,熵高则混乱度高。)

转换的能量越大,创造出来的新状态就会越多,因此高能量系统不如低能量系统稳定,因为前者的熵较大。而且,凡是运动的系统都会有能量转换,热力学第二定律就是在说,所有封闭系统最终都会趋向混乱度最大的状态,除非外部注入能量。

(上图中,冰块是分子的有序排列,吸收能量后,变成液体水,分子排列变得无序。)

5、

熵让我理解了一件事,如果不施加外力影响,事物永远向着更混乱的状态发展。比如,房间如果没人打扫,只会越来越乱,不可能越来越干净。

(上图中,如果不花费能量打扫,房间总是越来越乱。)

为什么”世间好物不坚牢,彩云易散琉璃脆”?就是因为事物维持美好的状态是需要能量的,如果没有能量输入,美好的状态就会结束。

这就是我世界观的变化。我从此认识到,人类社会并非一定会变得更进步、更文明。相反地,人类如同宇宙的其他事物一样,常态和最终命运一定是变得更混乱和无序。过去五千年,人类文明的进步只是因为人类学会利用外部能量(牲畜、火种、水力等等)。越来越多的能量注入,使得人类社会向着文明有序的方向发展。

(上图中,经过130多亿年的膨胀,宇宙变得越来越无序了。)

6、

工业革命以后,人类社会的进步速度加快了,变得更加先进有序,消耗的能量也指数级地增长:水力不够了用煤炭,煤炭不够了用石油,石油不够了用核能。

能量消耗越大,就会产生越多的熵。因此,人类社会始终处于一种矛盾状态:整个社会变得更加有序和严密的同时,无序和混乱也在暗处不断滋长。

我们只是依靠更大的能量输入,在压制熵的累积。不断增加的熵,正在各种方面爆发出来:垃圾污染、地球变暖、土地沙化、PM2.5、物种灭绝……甚至心理疾病、孤独感和疏离感的暴增,我认为都是熵的增加对人类精神造成的结果。

我们需要能量,让世界变得有秩序,但这样是有代价的。物理学告诉我们,没有办法消除熵和混乱,我们只是让某些局部变得更有秩序,把混乱转移到另一些领域。

7、

人类社会正在加速发展。表面上,我们正在经历一个减熵过程,一切变得越来越有秩序,自动化带来了便捷。但是,能量消耗也在同步放大,为了解决越来越多的熵,我们不得不寻找更多的能量,这又导致熵的进一步增加,从而陷入恶性循环。

迄今为止,人类一直能够找到足够的能量,解决熵带来的混乱。但是,这种解决方式正变得捉襟见肘。如果我们继续像现在这样加速发展,那么终有一天会出现能量缺口,地球上的能量不足以解决熵,那时一切就会发生逆转,仿佛细小的裂缝演变成巨大的雪崩,秩序开始崩塌,世界走向混乱。

([说明] 本文出自我正在写的新书《未来世界的幸存者》,点击这里免费阅读全书。)

(完)

文档信息

尴尬集锦

发信人: Onlineness (Onlineness), 信区: Joke
标 题: 尴尬集锦
发信站: 水木社区 (Tue Apr 18 14:28:47 2017), 站内

(一)

姥姥家有一个圆形的水缸,姥姥叫我测一下周长,她好去做个盖子。我想,周长公式是2πr,那就要测r,就要找到圆心,于是我找了两根撑衣杆,交叉之后在缸上面找圆心。

我妈看了半天:“你在干啥子?”
“测半径算周长啊”
“你不能直接拿根毛线绕一圈吗???”

(二)

陪闺密去妇科做检查(要脱裤子的那种)闺密出来后表情各种纠结,她说里面那医师的助理是个男的,我说男的怕什么?她快要哭出来说:“他是以前我们学校的,追了我两年,我一直都回避他,连手都没给他碰过,老子今天却主动把他最想看的地方送给他看了!!!

(三)

和女神约去啪啪啪,完事儿了刚出门,被一闷棍子打倒在地上了,醒来在医院,床边守着女神,还有个三岁多的小女孩喊我爸爸。我问女神咋回事?她说我出门没站稳,头撞在墙角,在医院一趟就是三年多,我们的女儿都快三岁了!一想到将近三年没尽父亲的义务,也没有照顾妻子,我就惭愧地低下了头。

(四)

世界上最尴尬的四件事:
第一,砍了树做成纸,在纸上面写着爱护森林;第二,拿着父母的血汗钱,在KTV里面唱父亲你辛苦了;第三,女人每天和很多男人在暧昧,却说着世界上没有好男人。第四,明明同意以上说法,却没有点Like

※ 来源:·水木社区 http://www.newsmth.net·[FROM: 202.108.65.*]

Re: 舌尖上的走进科学

发信人: iwannabe (I wanna be), 信区: Joke
标 题: Re: 舌尖上的走进科学
发信站: 水木社区 (Tue Apr 18 09:58:13 2017), 站内

猫不知道。。。我得讲个耗子的故事。。

去年在重庆做实验,考察辣椒素对肠道菌群的影响,是否可以减肥等等。。当然,用的是
买的模式小鼠。。

实验发现,特么实验组体重掉的超级快,师兄满怀信心要发个大paper,然而一称鼠粮(
当然拌了些辣椒素),特么这群耗子宁可饿了一周也没怎么吃鼠粮,体重特么怎么会不减
少??

然后实验就暂停了,师兄就把满怀信心配的几十斤辣的鼠粮塞柜子里赖。。实验室老师看
到了,说这样怕招耗子。。师兄呵呵一下,太辣,耗子都不吃。。

一个暑假过去了,再次打开那个柜子,巨辣鼠粮只剩了一小半,然后是实验室各个抽屉都
清理不干净的老鼠屎。。

师兄没考虑到重庆本地耗子的人生经验,个人奋斗和历史进程。。

Too young

作者:狒狒
链接:https://www.zhihu.com/question/26972502/answer/106949581
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

【 在 acce (如有雷同概不负责,如被其实纯属巧合) 的大作中提到: 】
: 一直都有说法是口味在孕育期间奠定基础,基因的表达受到环境的影响定向优化并塑造
: 了身体结构
: 但是,并不在基因中注入

※ 来源:·水木社区 newsmth.net·[FROM: 211.99.222.*]

博士相亲的故事

发信人: slslzj (slslzj), 信区: Joke
标 题: 博士相亲的故事
发信站: 水木社区 (Mon Apr 17 11:22:21 2017), 站内

一大龄男博士被介绍给一个同年的女博士,奇迹在此刻发生,他的第一反应是去搜了对方的博士论文研读一下。
同一时间,女博士也正在干同样的事情,有一天,女博士找到了男博士:“我找到了你论文的抄袭的地方。”
男博士:”别说了,我娶你还不行么!“

※ 来源:·水木社区 http://www.newsmth.net·[FROM: 115.171.27.*]

Category

Archives