How to make an OUTGOING websocket connection request in GO

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

How to make an OUTGOING websocket connection request in GO

问题

我发现很多关于如何在Go中创建接受ws连接的websocket服务的示例,但没有一个示例是用于发送ws连接的。
由于ws请求最初是作为普通的rest请求执行的,我尝试了以下代码:

request, err := http.NewRequest("GET", "ws://localhost:8081/ws", nil)
if err != nil {
	fmt.Println(err)
	return
}

_, err = http.DefaultClient.Do(request)
if err != nil {
	fmt.Println(err)
	return
}
client := newClient(*websocket.Conn) // 我如何获取*websocket.Conn?
go client.Read()
go client.Write()
clientsMap.Add(client)

但显然这不起作用,我得到了一个不支持的协议方案"ws"的错误。
我该如何建立ws连接并获取*websocket.Conn?

英文:

I find a lot of examples of how to make a websocket service in Go that accepts ws connections, but not one to send them.
Since the ws request is initially executed as a normal rest request, I try something like this

request, err := http.NewRequest("GET", "ws://localhost:8081/ws", nil)
if err != nil {
	fmt.Println(err)
	return
}

_, err = http.DefaultClient.Do(request)
if err != nil {
	fmt.Println(err)
	return
}
client := newClient(*websocket.Conn) // how i can get *websocket.Conn?
go client.Read()
go client.Write()
clientsMap.Add(client)

But this obviously doesn't work, I get an unsupported protocol scheme "ws" error.
How do I make a ws connection and get *websocket.Conn?

答案1

得分: 2

如果你正在使用godoc websocket,你可以使用该包中的Dialer.DialDialer.DialContext。以下是如何使用的示例代码。

dial, _, err := websocket.DefaultDialer.Dial("ws://localhost:8081/ws", nil)
if err != nil {
	log.Fatalln(err)
}
defer dial.Close()

err = dial.WriteMessage(websocket.TextMessage, []byte("hello"))
if err != nil {
	log.Fatalln(err)
}

err = dial.WriteMessage(websocket.TextMessage, []byte("world"))
if err != nil {
	log.Fatalln(err)
}

完整的代码可以在这里查看。

package main

import (
	"log"
	"net/http"
	"sync"

	"github.com/gorilla/websocket"
)

func main() {
	wg := sync.WaitGroup{}
	wg.Add(2)

	// 服务器
	go func() {
		defer wg.Done()

		var (
			upgrader = &websocket.Upgrader{}
			stopChan = make(chan struct{})
		)

		http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
			defer func() {
				close(stopChan)
			}()

			upgrade, err := upgrader.Upgrade(w, r, nil)
			if err != nil {
				return
			}
			for {
				msgType, msg, err := upgrade.ReadMessage()
				if err != nil {
					log.Println("连接已关闭,", err)
					return
				}
				log.Println(msgType, string(msg))
			}
		})

		go func() {
			err := http.ListenAndServe("localhost:8081", nil)
			if err != nil {
				log.Fatalln(err)
			}
		}()

		<-stopChan
	}()

	// Dialer (客户端)
	go func() {
		defer wg.Done()

		dial, _, err := websocket.DefaultDialer.Dial("ws://localhost:8081/ws", nil)
		if err != nil {
			log.Fatalln(err)
		}
		defer dial.Close()

		err = dial.WriteMessage(websocket.TextMessage, []byte("hello"))
		if err != nil {
			log.Fatalln(err)
		}

		err = dial.WriteMessage(websocket.TextMessage, []byte("world"))
		if err != nil {
			log.Fatalln(err)
		}
	}()

	wg.Wait()
}

// 输出
// 2022/09/17 07:18:57 1 hello
// 2022/09/17 07:18:57 1 world
// 2022/09/17 07:18:57 连接已关闭, websocket: close 1006 (异常关闭): 意外的 EOF
英文:

If you are using gorilla websocket, you can use Dialer.Dial or Dialer.DialContext from that package. Below is the example on how to use it.

dial, _, err := websocket.DefaultDialer.Dial(&quot;ws://localhost:8081/ws&quot;, nil)
if err != nil {
log.Fatalln(err)
}
defer dial.Close()
err = dial.WriteMessage(websocket.TextMessage, []byte(&quot;hello&quot;))
if err != nil {
log.Fatalln(err)
}
err = dial.WriteMessage(websocket.TextMessage, []byte(&quot;world&quot;))
if err != nil {
log.Fatalln(err)
}

For the full code, you can check this.

package main
import (
&quot;log&quot;
&quot;net/http&quot;
&quot;sync&quot;
&quot;github.com/gorilla/websocket&quot;
)
func main() {
wg := sync.WaitGroup{}
wg.Add(2)
// Server
go func() {
defer wg.Done()
var (
upgrader = &amp;websocket.Upgrader{}
stopChan = make(chan struct{})
)
http.HandleFunc(&quot;/ws&quot;, func(w http.ResponseWriter, r *http.Request) {
defer func() {
close(stopChan)
}()
upgrade, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
for {
msgType, msg, err := upgrade.ReadMessage()
if err != nil {
log.Println(&quot;connection closed,&quot;, err)
return
}
log.Println(msgType, string(msg))
}
})
go func() {
err := http.ListenAndServe(&quot;localhost:8081&quot;, nil)
if err != nil {
log.Fatalln(err)
}
}()
&lt;-stopChan
}()
// Dialer (Client)
go func() {
defer wg.Done()
dial, _, err := websocket.DefaultDialer.Dial(&quot;ws://localhost:8081/ws&quot;, nil)
if err != nil {
log.Fatalln(err)
}
defer dial.Close()
err = dial.WriteMessage(websocket.TextMessage, []byte(&quot;hello&quot;))
if err != nil {
log.Fatalln(err)
}
err = dial.WriteMessage(websocket.TextMessage, []byte(&quot;world&quot;))
if err != nil {
log.Fatalln(err)
}
}()
wg.Wait()
}
// output
// 2022/09/17 07:18:57 1 hello
// 2022/09/17 07:18:57 1 world
// 2022/09/17 07:18:57 connection closed, websocket: close 1006 (abnormal closure): unexpected EOF

huangapple
  • 本文由 发表于 2022年9月17日 15:00:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/73752836.html
匿名

发表评论

匿名网友

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

确定