Hello Flask Socket.IO [2]


Hello Flask Socket.IO 系列文章二。本文延续文章一的开发,基于 Flask Socket.IO 继续实现广播和点对点通信。

相关文章:
Hello Flask Socket.IO [1]
相关 Github 源码

版权声明:本文为 frendy 原创文章,可以随意转载,但请务必在明确位置注明出处。


广播


广播相对容易,在 emit 时添加 broadcast=True 即可向所有 Socket Client 端发送消息。下面搭建了个简易的Demo,实现了在网页端发送一个字符串到所有 Android 客户端的示例。

1.在服务器端加入广播监听处理。当接收到广播发送请求时向 App 发送广播:
@socketio.on('broadcast')
def do_broadcast(message):
	print(message['data'])
	emit('app broadcast', {'data': message['data']}, broadcast=True)
2.在 index.html 里加入广播发送按钮:

image

<button type="button" onclick="push()"> Click to Push </button>
<input id='input' name='input' value='***** Test Broadcast' />

<script type="text/javascript" charset="utf-8">
	function push() {
		var message = document.getElementsByTagName('input')[0].value;
		socket.emit('broadcast', {'data': message});
		alert("Send Broadcast!");
	}
</script>
3.在 App 添加 SocketIO 的广播监听器即可:
//4.注册广播接收监听器
mSocket.on("app broadcast", onAppBroadcast);

private Emitter.Listener onAppBroadcast = new Emitter.Listener() {
	@Override
	public void call(final Object... args) {
		mActivity.runOnUiThread(new Runnable() {
			@Override
			public void run() {
				try {
					JSONObject data = (JSONObject) args[0];
					mView.showMessage(data.getString("data"));
				} catch (JSONException e) {
					e.printStackTrace();
				}
			}
		});
	}
};

点对点


点对点相对麻烦,服务器端怎样获取并维护 Client A/B/C… 端 Socket?这里采用了一个比较简单粗暴的办法,以 Client 端设备 ID 作为自定义事件,从而标识区分各个 Client 端,并在 Client 注册相应的事件监听来获取消息。后续有空再进一步实践 namespace 和 room 等概念(目前未声明时应该用的是默认的 namespace 和 room,指定后可以实现一对多吧?下回分解)。

1.在服务器端加入注册监听处理。目前注册监听只用于获取 Client 端的设备 ID,后续可以基于设备 ID 到服务端换取 token 作为自定义事件:
@socketio.on('register')
def my_event(message):
	print('uid=%s' % (message['data']))
2.在服务器端加入点对点消息监听处理。当接收到消息发送请求时会向 App 发送自定义事件消息:
@socketio.on('p2p')
def do_p2p_message(message):
	emit(message['id'], {'data': message['data']}, broadcast=True)
	print('to=%s, message=%s' % (message['id'], message['data']))
3.在 index.html 里加入点对点消息发送按钮:

image

<button type="button" onclick="pushP2P()"> Click to Push P2P Message</button>
<input id='input2' name='input2' value='请输入 Android ID' />
<input id='input3' name='input3' value='***** Test P2P Message' />

<script type="text/javascript" charset="utf-8">
	function pushP2P() {
		var androidId = document.getElementsByTagName('input')[1].value;
		var message = document.getElementsByTagName('input')[2].value;
		var data = {'id': androidId, 'data': message};
		socket.emit('p2p', data);
		alert("Send P2P Message!");
	}
</script>
4.在 App 添加 SocketIO 的自定义消息监听器即可:
//5.向服务器注册点对点通信监听
try {
	JSONObject data = new JSONObject();
	data.put("data", mAndroidID);
	mSocket.emit("register", data);
} catch (JSONException e) {
	e.printStackTrace();
}
mSocket.on(mAndroidID, onP2PMessage);

private Emitter.Listener onP2PMessage = new Emitter.Listener() {
	@Override
	public void call(final Object... args) {
		mActivity.runOnUiThread(new Runnable() {
			@Override
			public void run() {
				try {
					JSONObject data = (JSONObject) args[0];
					mView.showMessage(data.getString("data"));
				} catch (JSONException e) {
					e.printStackTrace();
				}
			}
		});
	}
};


欢迎来撩

frendy

It will shine for us...