亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

golang net.Conn 可以在有新消息時得到通知嗎?

golang net.Conn 可以在有新消息時得到通知嗎?

Go
斯蒂芬大帝 2023-05-22 17:02:52
我嘗試實現的我正在實現一個客戶端發送和接收 unixpackets 并與已經用 C++ 實現的服務器交互。至此,客戶端可以成功接收和向服務器發送數據包。但是我用了一個for循環,一直調用Recv看有沒有新消息。我做了什么我實現了一個 Packet 類,以便客戶端和服務器可以遵循相同的規則對消息進行編碼和解碼。Transport 是一個包裝一個net.Conn. Client由Transport、接收Packet和發送Packet組成。我使用for 循環不斷調用Recv以查看是否有新消息到達net.Conn。type Packet struct {    Length      uint32    Data        []byte    ReadOffset  uint32    WriteOffset uint32}type Transport struct {    url   string    conn  net.Conn}// connect to urlfunc (transport *Transport) Dial(url string) error {    c, err := net.Dial("unixpacket", url)    if err != nil {        return err    }    transport.url = url    transport.conn = c    return nil}// sending Packetfunc (transport *Transport) Send(p *Packet) bool {    readBuffer := (p.Data)[p.ReadOffset : p.WriteOffset]    _, err := transport.conn.Write(readBuffer)    if err != nil {        return false    }    return true}// receiving Packetfunc (transport *Transport) Recv(p *Packet) bool {    writeBuffer := (p.Data)[p.WriteOffset :]    _, err := transport.conn.Read(writeBuffer)    if err != nil {        return false    }    return true}type Client struct {    Transport  *Transport    RecvPacket *Packet    SendPacket *Packet}// keep checking transportfunc (c *Client) ReadFromTransport() {    for {        time.Sleep(20 * time.Millisecond)        if c.Transport.Recv(c.RecvPacket) == false {            continue        }    }}問題有沒有一種方法可以net.Conn在新消息到達時通知 get 而不是使用 for 循環?
查看完整描述

2 回答

?
MMTTMM

TA貢獻1869條經驗 獲得超4個贊

有沒有一種方法可以在新消息到達 net.conn 時通知 net.conn 而不是使用 for 循環?

不,不在標準包中。

在循環中從 net.Conn 讀?。ǎ┦菣z測消息到達的常用方法。如果您需要執行多個并發任務,您可以將循環封裝在一個寫入通道的 goroutine 中,并包裝一個 for 循環和 select around 從該通道讀取。

查看完整回答
反對 回復 2023-05-22
?
一只斗牛犬

TA貢獻1784條經驗 獲得超2個贊

net.conn.Read自動阻塞,直到連接上的數據可用。您不必循環等待數據出現。


有一個簡單的套接字服務器(在 python3 中只是為了清除語言障礙)


import socket, os, sys


addr='/tmp/a_unix_socket'


if os.path.exists(addr):

  os.unlink(addr)

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)


sock.bind(addr)

sock.listen(1)


while True:

  print("Waiting for connection", file=sys.stderr)

  conn, client_addr = sock.accept()

  data =conn.recv(128)

  print("Recived {}".format(data))

  conn.sendall(b'thank you')

  conn.close()

我可以這樣制作一個 golang 客戶端:


package main


import (

  "net"

  "fmt"

)


func main() {

  conn, err := net.Dial("unix", "/tmp/a_unix_socket")

  if err != nil {

    panic(err)

  }

  conn.Write([]byte("here is data"))

  result := make([]byte, 128)

  _, err = conn.Read(result)

  if err != nil {

    panic(err)

  }

  fmt.Println("Response: ", string(result))

  conn.Close()

}

服務器端說:


$ python3 ./t.py

Waiting for connection

Recived b'here is data'

Waiting for connection

客戶端說:


$ go run t.go

Response:  thank you

net.Conn此處未配置讀取超時,因此它愿意等待所需的時間。


我還要提一下:


if err != nil {

    return false

}

這隱藏了無區別的“錯誤”響應背后的錯誤。如果發生不可恢復的錯誤(比方說服務器關閉連接),您的客戶端將無限期循環(在此過程中占用大量 CPU)。如果您需要暴露錯誤,請返回它們。如果您想偷懶進行概念驗證,panic()如果必須的話,可以使用它們,但不要為所有這些返回相同的結果,否則您將無法正確處理個別錯誤情況。在您的情況下,這是一個有爭議的問題,因為您for無論如何都不需要循環。


查看完整回答
反對 回復 2023-05-22
  • 2 回答
  • 0 關注
  • 193 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號