当前位置: 首页 > 知识库问答 >
问题:

conn(net.conn)并不总是在套接字上写入

姜俊民
2023-03-14

我用一个服务器和客户端做了一个应用程序,用TCP套接字发送信息

问题是,如果函数zfs。ReceiveSnapshot(在服务器端)不返回错误(err==nil),conn.写([]byte("0"))不工作,客户端没有收到任何字节继续,它不能关闭连接...

我给你看服务器和客户端的代码

服务器:

package main

import (
    "net"
    "github.com/mistifyio/go-zfs"
)

func main() {
    // Listen for incoming connections
    l, _ := net.Listen("tcp", ":7766")

    // Close the listener when the application closes
    defer l.Close()
    fmt.Println("Listening on port 7766...")
    for {
        // Listen for an incoming connection.
        conn, _ := l.Accept()
        // Handle connections in a new goroutine.
        go handleRequest(conn)
    }
}

// Handles incoming requests
func handleRequest(conn net.Conn) {
    // Receive snapshot
    _, err := zfs.ReceiveSnapshot(conn, "tank/replication")
    if err != nil {
        conn.Write([]byte("1"))
        zfs.ReceiveSnapshot(conn, "tank/replication")
        conn.Close()
    } else {
        conn.Write([]byte("0"))
        conn.Close()
    }
}

客户:

package main

import (
    "net"
    "github.com/mistifyio/go-zfs"
)

func main() {
    conn, _ := net.Dial("tcp", "192.168.99.5:7766")

    for i := 0; i < 1; i++ {
        // Get all snapshots in tank/test
        take, _ := zfs.Snapshots("tank/test")

        // Select snapshots
        snap := take[0].Name
        ds1, _ := zfs.GetDataset(snap)

        // Send first snapshot
        ds1.SendSnapshot(conn)
        defer conn.Close()

        buff := make([]byte, 1024)
        n, _ := conn.Read(buff)

        if n != 0 {
            snap = take[1].Name
            ds2, _ := zfs.GetDataset(snap)
            zfs.SendSnapshotIncremental(conn, ds1, ds2, zfs.IncrementalStream)
            conn.Close()
        }
    }
}

[编辑]:如果接收快照返回错误,控制。写([]byte)写"1",客户端接收到它,执行SendSnapshot增量(如果n!=0)并关闭客户端的连接...但是,如果ReceiveSnapshot不返回错误,则返回。写([]byte)不写0,只是我用ctrl C关闭服务器端的连接

共有2个答案

萧德庸
2023-03-14

[编辑

解决这个问题的几个修改。。。

服务器:

func handleRequest(conn net.Conn) {
    // Number of snapshots in server side
    take, _ := zfs.Snapshots("tank/replication")
    count := len(take)
    if count < 1 {
        conn.Write([]byte("0"))
    } else {
        conn.Write([]byte("1"))
    }

    // Receive snapshot
    zfs.ReceiveSnapshot(conn, "tank/replication")
}

count返回服务器拥有的快照数量,因此如果没有快照,客户端将执行该案例,在另一种情况下为默认情况。

客户:

func main() {
    // Get the last two snapshots
    take, _ := zfs.Snapshots("tank/test")
    snap := take[0].Name
    ds1, _ := zfs.GetDataset(snap)
    snap = take[1].Name
    ds2, _ := zfs.GetDataset(snap)

    // New server connection
    conn, _ := net.Dial("tcp", "192.168.99.5:7766")

    // Read data of server side
    buff := bufio.NewReader(conn)
    n, _ := buff.ReadByte()

    // Execute the correct case
    switch string(n) {
    case "0":
        ds1.SendSnapshot(conn)
        conn.Close()
    default :
        zfs.SendSnapshotIncremental(conn, ds1, ds2, zfs.IncrementalStream)
        conn.Close()
    }
}

我不知道这个解决方案是否很好,但它是有效的!

刘骏祥
2023-03-14

我认为问题在于以下几方面:

buff := make([]byte, 1024)
n, _ := conn.Read(buff)

在本例中,n是读取的字节数,而不是其中任何一个字节的值。

我会:

buff := make([]byte, 1)
n,err := conn.Read(buff)
buff = buff[:n]
if len(buff) == 0 {
   //error
}

if(buff[0] != 0){...
 类似资料:
  • 问题内容: 我有多个Goroutines共享一个net.Conn对象。他们可以同时发出写呼叫吗? 我主要关心的是部分完成的Write调用。假设我打算写100个字节,但是只发送了30个字节,因此我需要再发送70个字节。为此,我通常会编写一个循环: 但是我看到Go在net.Conn.Write行号318中实现了这个循环,它是通过锁来实现的。 但是,在Windows实现上,除了调用WSASend之外没有

  • 我想从Java应用程序通过套接字发送一个简单的。我的问题是,如果不在的末尾添加'\n',编写就不起作用。我必须添加这个“\n”还是有更优雅的解决方案? 这是我的代码:

  • 如何通过tcp套接字接收struct并输出到文件?我有一个结构,这是一个包,我试图通过套接字发送它,在客户端接收它,并写入文件。我使用一个空指针作为缓冲区来存储文件数据 到目前为止,我有 我能够访问客户端的 id、int,但是当我将数据写出到文件时。文件似乎已损坏。 更新: 服务器有一个打开的文件,它将从该文件中读取数据,并将其制成一个数据包,然后将该数据包发送给客户端。 客户端还将打开一个文件进

  • 我转向你,在这件事上我一直把头撞在墙上。 我正在做一个小的socket编程,我可以看到当我把它放出来。println(“…”)while循环之前的代码行(in.readLine())它工作正常,但我需要它位于循环内部。 说清楚一点,我没有看到任何错误。我只是看不到此应用程序的客户端显示文本。它看起来好像在工作,但事实并非如此。此外,我也不控制该应用程序的客户端,它由通过TCP连接到此套接字侦听器应

  • 在我的客户端/服务器应用程序中,我的客户端wiil与服务器通信有两个功能:客户端要么向服务器请求数据,要么发送数据,以便服务器保存。我对这两种方法都使用一个套接字,要使用的方法由发送的第一个字节定义。如果第一个字节是“1”,它将请求数据。如果是“2”,它将发送数据(数据字节在“2”字节之后发送)。它非常适合发送数据。但是当我请求数据时,只要我不读取客户端中的套接字流,它就可以工作。这就像如果我在发

  • 我制作了一个带有阻塞套接字的小型套接字echo服务器(请参见下面的代码),但是select语句始终返回0,即使有消息要读取。其他的都管用。如果通过简单地将1赋给来替换select语句,则服务器可以工作。 服务器在虚拟机中运行在Ubuntu上,而客户端在主机系统上(Windows7 professional)。我的服务器IDE是Eclipse3.8,它使用OpenSSL1.0.1j。 要让这段代码工