Al03's blog

WebSocket

WebSocket做为H5的标准自发布以来,主流浏览器都已支持,应用场景也很多,如Google的Docs多人协作功能,以及各种聊天直播应用。 有益于WebSocket,这使得网页不再局限于以前的内容呈现功能,上升到应用级别。

这篇文章我们来简单实现一个WebSocket

Server

Server 使用的是Ruby的 EM-WebSocket gem。

构建 server 的实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require "em-websocket"

EventMachine.run do
@channel = EM::Channel.new

EventMachine::WebSocket.start(host: "0.0.0.0", port: 8080, debug: true) do |ws|
ws.onopen do
sid = @channel.subscribe { |msg| ws.send(msg) }
@channel.push("#{sid} connected")

ws.onmessage { |msg| @channel.push("<#{sid}> #{msg}") }

ws.onclose { @channel.unsubscribe(sid) }
end
end
end

server 接受8080 端口的 WebSocket 连接。当一个新的client连接后,它会注册一个内部 channel,每次 client 发送的数据都会 push 到这个 channel ,当 channel 有数据时,会发送到所有已连接的 client。Client 是根据他们的注册ID(自增数字型)来区分的。当 client 断开连接就会取消 channel 的注册。

Browser Client

浏览器的WebSocket客户端 JavaScript 代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$(document).ready(function() {
ws = new WebSocket("ws://" + location.hostname + ":8080/");

ws.onmessage = function(event) {
$("#messages").append("<p>" + event.data + "</p>");
};

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

ws.onopen = function() {
console.log("Connected");
ws.send("Hello from " + navigator.userAgent);
};

$("#new-message").bind("submit", function(event) {
event.preventDefault();
ws.send($("#message-text").val());
$("#message-text").val("");
});
});

HTML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="client.js"></script>
</head>

<body>
<div id="messages">
</div>

<form id="new-message">
<input id="message-text" type="text" />
<input type="submit" value="Send">
</form>
</body>
</html>

连接 server 的8080端口,然后实现成功建立连接的回调,收到信息的回调,关闭连接的回调。还有发送消息的 event handler。

在HTML和JS文件的目录内使用 python -m SimpleHTTPServer 开启一个 HTTPServer。然后打开localhost:3000

iOS client

iOS 可以使用的是一个WebSocket client 框架 Starscream

使用 Starscream 连接 server:

1
2
3
4
5
6
override func viewDidLoad() {
super.viewDidLoad()
socket = WebSocket(url: URL(string: "ws://localhost:8080")!)
socket.delegate = self
socket.connect()
}

真机运行的话要将localhost换成 server 的IP。

然后实现WebSocketDelegate协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extension ViewController : WebSocketDelegate {
public func websocketDidConnect(socket: Starscream.WebSocket) {

}

public func websocketDidDisconnect(socket: Starscream.WebSocket, error: NSError?) {

}

public func websocketDidReceiveMessage(socket: Starscream.WebSocket, text: String) {

}

public func websocketDidReceiveData(socket: Starscream.WebSocket, data: Data) {

}
}

发送消息:

1
2
3
func sendMessage(_ message: String) {
socket.write(string: message)
}

希望通过上面的例子能够让大家了解WebSocket的简单使用。