Golang WebSocket 处理程序

huangapple go评论121阅读模式
英文:

Golang websocket handler

问题

我在使用Node.js写了很长时间之后,开始学习Golang,并且对如何实现处理程序有些好奇。我选择使用Gorilla Websocket,因为我了解到它是最可靠的包。

例如,在socket.io中,你可以使用简单的socket.on函数,根据传入的JSON中的"name"参数调用一个函数。

Gorilla websocket没有实现这样的功能,所以我的问题是,我是否需要实现类似socket.io的逻辑来实现我想要的功能?

也就是说,根据在websocket中传输的值执行某个过程?

如果是这样的话,我需要分别在客户端(我在前端使用AngularJS)和服务器端自己实现它——在AngularJS中根据JSON中的值进行switch case语句,然后在Go中进行相同的操作。而且,这是最高效的方式吗?

谢谢!

英文:

I've started learning Golang after writing in Node.js for a long time and I'm a bit curious as to how am I to implement a handler - I've opted to use Gorilla Websocket since I understood it's the most reliable package out there.

In socket.io for example you have the simple socket.on function that allows me to call a function based on the "name" parameter passed in JSON.

Gorilla websocket doesn't implement such a thing, so my question is am I to sort of implement the logic behind socket.io in order to achieve what I want ?

As in do a certain procedure based on the value transferred in the websocket ?

If so - I need to implement it both client (I'm using AngularJS on the front-end) and server side separately by my own - make a switch case statement based on a value I get in JSON both in AngularJS for the front-end and in Go for the back-end, and also - is that the most efficient way ?

Thanks !

答案1

得分: 5

如果你已经使用JavaScript一段时间了,实现自己的socket.onsocket.emit版本非常容易。这是我为自己的项目制作的一个版本,如果你需要的话可以使用:

  1. // 例如:
  2. // let socket = new Socket("ws://w/e");
  3. // socket.on('connected', () => { console.log('Connected'); });
  4. // socket.emit('lobby join', { data: { username: 'Boo' } });
  5. // 使用ES2015和Babel
  6. import { EventEmitter } from 'events';
  7. class Socket {
  8. constructor(wsurl, ee = new EventEmitter()) {
  9. let ws = new WebSocket(wsurl);
  10. this.ee = ee;
  11. this.ws = ws;
  12. ws.onmessage = this.message.bind(this);
  13. ws.onopen = this.open.bind(this);
  14. ws.onclose = this.close.bind(this);
  15. }
  16. on(name, fn) {
  17. this.ee.on(name, fn);
  18. }
  19. off(name, fn) {
  20. this.ee.removeListener(name, fn);
  21. }
  22. emit(name, data) {
  23. const message = JSON.stringify({ name, data });
  24. this.ws.send(message);
  25. }
  26. message(e) {
  27. try {
  28. const msgData = JSON.parse(e.data);
  29. this.ee.emit(msgData.name, msgData.data);
  30. } catch (err) {
  31. let error = {
  32. message: err
  33. };
  34. console.log(err);
  35. this.ee.emit(error.message);
  36. }
  37. }
  38. open() {
  39. this.ee.emit('connected');
  40. }
  41. close() {
  42. this.ee.emit('disconnected');
  43. }
  44. }
  45. export default Socket;

这样你就可以使用常见的socket.on('event', fn);等方法了。

至于服务器端的处理:

对于接收消息,我个人只是创建了一个switch语句,将传入的字符串与函数匹配,例如:

  1. // readPump将websocket连接中的消息传输到hub。
  2. func (c *connection) readPump() {
  3. defer c.ws.Close()
  4. for {
  5. _, message, err := c.ws.ReadMessage()
  6. if err != nil {
  7. break
  8. }
  9. var incMessage interface{}
  10. err = json.Unmarshal(message, &incMessage)
  11. if err != nil {
  12. log.Println(err)
  13. }
  14. incMessageMap := incMessage.(map[string]interface{})
  15. switch incMessageMap["name"] {
  16. case "lobby join":
  17. // 处理加入操作
  18. case "lobby leave":
  19. // 处理离开操作
  20. }
  21. }
  22. }

对于发送消息,我在连接上有一个send channel,它存储在一个映射中,当我需要发送时,我有一个简单的结构体,它接受消息名称和数据,例如:

  1. type wsMsg struct {
  2. Name string `json:"name"`
  3. Data map[string]interface{} `json:"data"`
  4. }
  5. c.send <- wsMsg{
  6. "user joined",
  7. map[string]interface{}{
  8. "username": "Booh",
  9. },
  10. }

然后在客户端,它会以如下形式出现:

  1. socket.on('user joined', (msg) => {
  2. console.log(msg); // { username: "Booh" }
  3. });

我建议查看gorilla的示例:https://github.com/gorilla/websocket/tree/master/examples/chat

英文:

If you've been using Javascript for a while it is really easy to implement your own version of socket.on and socket.emit here is one I made for my own projects but you can have it if you need,

  1. // e.g.
  2. // let socket = new Socket(&quot;ws://w/e&quot;);
  3. // socket.on(&#39;connected&#39;, () =&gt; { console.log(&#39;Connected&#39;); });
  4. // socket.emit(&#39;lobby join&#39;, { data: { username: &#39;Boo&#39; } });
  5. // Using ES2015 with Babel
  6. import {EventEmitter} from &#39;events&#39;;
  7. class Socket {
  8. constructor(wsurl, ee = new EventEmitter()) {
  9. let ws = new WebSocket(wsurl);
  10. this.ee = ee;
  11. this.ws = ws;
  12. ws.onmessage = this.message.bind(this);
  13. ws.onopen = this.open.bind(this);
  14. ws.onclose = this.close.bind(this);
  15. }
  16. on(name, fn) {
  17. this.ee.on(name, fn);
  18. }
  19. off(name, fn) {
  20. this.ee.removeListener(name, fn);
  21. }
  22. emit(name, data) {
  23. const message = JSON.stringify({name, data});
  24. this.ws.send(message);
  25. }
  26. message(e) {
  27. try {
  28. const msgData = JSON.parse(e.data);
  29. this.ee.emit(msgData.name, msgData.data);
  30. }
  31. catch(err) {
  32. let error = {
  33. message: err
  34. }
  35. console.log(err)
  36. this.ee.emit(error.message)
  37. }
  38. }
  39. open() {
  40. this.ee.emit(&#39;connected&#39;);
  41. }
  42. close() {
  43. this.ee.emit(&#39;disconnected&#39;);
  44. }
  45. }
  46. export default Socket

This will let you use your common socket.on(&#39;event&#39;, fn); and what not

As for handling it on the servers end:

For receiving messages, I personally just make a switch statement that will match an incoming string to a function, e.g.:

  1. // readPump pumps messages from the websocket connection to the hub.
  2. func (c *connection) readPump() {
  3. defer c.ws.Close()
  4. for {
  5. _, message, err := c.ws.ReadMessage()
  6. if err != nil {
  7. break
  8. }
  9. var incMessage interface{}
  10. err = json.Unmarshal(message, &amp;incMessage)
  11. if err != nil {
  12. log.Println(err)
  13. }
  14. incMessageMap := incMessage.(map[string]interface{})
  15. switch incMessageMap[&quot;name&quot;] {
  16. case &quot;lobby join&quot;:
  17. // Do something to handle joining
  18. case &quot;lobby leave&quot;:
  19. // Do something to handle leaving
  20. }
  21. }
  22. }

For sending them I have a send channel on my connections that is stored in a map and when I need to emit I have a simple struct that takes a message name, and data, e.g.:

  1. type wsMsg struct {
  2. Name string `json:&quot;name&quot;`
  3. Data map[string]interface{} `json:&quot;data&quot;`
  4. }
  5. c.send &lt;- wsMsg{
  6. &quot;user joined&quot;,
  7. map[string]interface{}{
  8. &quot;username&quot;: &quot;Booh&quot;,
  9. },
  10. }

Then on the client side it would come as

  1. socket.on(&#39;user joined&#39;, (msg) =&gt; {
  2. console.log(msg) // { username: &quot;Booh&quot; }
  3. });

I suggest looking at the examples on gorillas git: https://github.com/gorilla/websocket/tree/master/examples/chat

答案2

得分: 1

这是一个使用Golang的WebSocket来流式传输视频的工作示例。你可以在以下链接找到它:https://github.com/interviewparrot/OpenAVStream

如果你对这个示例满意,请告诉我。

英文:

Here is an working example of golang websocket to stream video
https://github.com/interviewparrot/OpenAVStream

Let me know if it is good enough

huangapple
  • 本文由 发表于 2016年1月6日 15:46:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/34628021.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定