Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 二进制。写入go块中的套接字_Sockets_Go - Fatal编程技术网

Sockets 二进制。写入go块中的套接字

Sockets 二进制。写入go块中的套接字,sockets,go,Sockets,Go,我正在尝试编写一个简单的客户机-服务器应用程序。它可以在同一台计算机上运行,但在两台不同的计算机上运行时会阻塞。这些电脑是一台树莓皮2和一台MacBookPro 问题是客户端以二进制方式阻塞。请在运行几次之后再写入。通常,接收数据的服务器打印它已接收的数据63,发送数据的客户端打印它将发送的数据64 如果我将截止日期通知服务器,它将超时退出。客户也有截止日期,但没有超时 我试着用一个简单的字节数组或一个整型来替换数据。它仍然会阻塞。但数据越小,正确的次数就越多 如果我删除客户端中的Printf函

我正在尝试编写一个简单的客户机-服务器应用程序。它可以在同一台计算机上运行,但在两台不同的计算机上运行时会阻塞。这些电脑是一台树莓皮2和一台MacBookPro

问题是客户端以二进制方式阻塞。请在运行几次之后再写入。通常,接收数据的服务器打印它已接收的数据63,发送数据的客户端打印它将发送的数据64

如果我将截止日期通知服务器,它将超时退出。客户也有截止日期,但没有超时

我试着用一个简单的字节数组或一个整型来替换数据。它仍然会阻塞。但数据越小,正确的次数就越多

如果我删除客户端中的Printf函数,它也会运行更长的时间

我还尝试用从套接字到STDIO的简单副本(我在这里的某个地方找到了一个技巧)来替换服务器的功能,但它仍然无法从binary.Write中获得

有什么想法吗

这是完整的来源。这里面有一些虚假的东西(比如计数循环),但其实很简单。还是我错了

package main

import (
    //  "bytes"
    "encoding/binary"
    "fmt"
    "io"
    "net"
    "os"
    "os/exec"
    "runtime/trace"
    "time"
    "unsafe"
)

type TheMessageType struct {
    X             int32
    RestOfMessage [1000]byte
}

func listener(theCounter int, active bool, f *os.File) {
    var message TheMessageType
    var err error
    var conn net.Conn

    count := theCounter

    for {
        // Dial the server
        fmt.Printf("LISTENER %d: connecting to socket\n", count)
        conn, err = net.Dial("tcp", "192.168.1.113:49152")
        if err != nil {
            fmt.Printf("LISTENER %d: not connected, retrying in 3 seconds\n", count)
            time.Sleep(3 * time.Second)
        } else {
            fmt.Printf("LISTENER %d: connected\n", count)
            break
        }
    }
    defer conn.Close()

    // Loop writing to socket
    for {
        // Set deadline
        // conn.SetDeadline(time.Now().Add(2 * time.Second))

        // Print some info
        fmt.Printf("LISTENER %d: writing from %v to %v\n", count, conn.LocalAddr(), conn.RemoteAddr())

        // Prepare message to write to socket
        message.X = int32(count)
        theString := fmt.Sprintf("%d", count)
        copy(message.RestOfMessage[:], theString)

        // binary write directly to socket
        fmt.Printf("LISTENER %d: binary.Write this: %d, %s\n", count, message.X, message.RestOfMessage)

        f.Sync()
        err = binary.Write(conn, binary.LittleEndian, message)

        f.Sync()
        fmt.Printf("LISTENER %d: written\n", count)
        // time.Sleep(50 * time.Millisecond)
        checkError(err, "LISTENER")

        count = count + 1
    }
}

func main() {
    var myMessage TheMessageType
    var ln net.Listener
    var conn net.Conn
    var err error
    var theCount int
    var avgspeed, speed float64
    var speedlist [10]float64

    curspeed := 0

    const listenerActive = true
    const mainActive = false

    f, err := os.Create("theFile.out")
    trace.Start(f)

    t0 := time.Now()
    t1 := time.Now()

    transferSize := unsafe.Sizeof(myMessage)

    fmt.Printf("MAIN: timestamp %s ; size of transfers is %d\n", t0.String(), transferSize)

    if mainActive {
        fmt.Println("MAIN: listen")
        ln, err = net.Listen("tcp", ":49152")
        fmt.Println("MAIN: defer")
        defer ln.Close()
        fmt.Println("MAIN: checkError")
        checkError(err, "MAIN")
    }

    // launch listener
    if listenerActive {
        go listener(theCount, listenerActive, f)
    }

    for theCount = 1; ; theCount++ {

        if mainActive {
            fmt.Println("MAIN: accept")
            conn, err = ln.Accept()
            checkError(err, "MAIN")

            exit := false

            for !exit {
                // Set deadline
                // conn.SetDeadline(time.Now().Add(2 * time.Second))

                // Print some info
                fmt.Printf("MAIN: reading on %v from %v\n", conn.LocalAddr(), conn.RemoteAddr())

                // move time
                t0 = t1

                // read from socket
                fmt.Println("MAIN: reader")

                f.Sync()
                err = binary.Read(conn, binary.LittleEndian, &myMessage)

                f.Sync()
                if err == io.EOF {
                    fmt.Println("EOF!")
                    exit = true
                    conn.Close()
                } else {
                    checkError(err, "MAIN")
                }

                // clear screen
                c := exec.Command("clear")
                c.Stdout = os.Stdout
                c.Run()

                // print received data
                fmt.Printf("MAIN: socket message received: %d, %s\n", myMessage.X, myMessage.RestOfMessage)

                // calculate speed & average
                t1 = time.Now()
                tdif := t1.Sub(t0)
                speed = float64(transferSize) / tdif.Seconds() / 1000000.0 * 8.0
                speedlist[curspeed] = speed
                curspeed = curspeed + 1
                if curspeed == 10 {
                    curspeed = 0
                }
                totalspeed := 0.0
                for i := 0; i < 10; i++ {
                    totalspeed += speedlist[i]
                }
                avgspeed = totalspeed / 10

                // print speed
                fmt.Printf("MAIN: avg mbit/s %9.2f ; actual mbit/s: %9.2f\n", avgspeed, speed)
                // time.Sleep(1 * time.Second)
            }
        }
    }
}

func checkError(err error, name string) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "%s: Fatal error: %s\n", name, err.Error())
        //      panic(fmt.Sprintf("%v", err.Error()))
        os.Exit(1)
    }
}

吉姆的回答是对的。Main进入一个繁忙的循环。我通过将一个频道传递给侦听器并在main的末尾等待它来解决这个问题。客户机在for循环之后“写入”到它,这是一个无限循环,所以main永远不会结束。从那以后,程序一直在传递数据。我会让它运行一夜,以确定

我只得到大约12.5Mbit/s,这有点滑稽。连接是1Gbit Wifi AC到Raspberry Pi的100mbit以太网交换机。但这是另一个问题


谢谢

当您的程序被阻止时,获取堆栈跟踪,以准确查看所有操作。我很想,但似乎无法获取跟踪。我尝试过使用runtime/trace,但还没有成功。它只写了“go 1.5 trace”什么都没有。我尝试了http pprof,但是当binary.Write阻塞时,它变得不可访问。显然,我的程序无法调用Stack(),因为它被阻塞了。当跟踪输出在阻塞之前运行时,是否有任何方法可以强制跟踪输出?我注意到的另一件事是:当它被二进制阻塞时。写入,CPU将达到100%。只需发送进程a
SIGQUIT
,它将打印堆栈跟踪并退出。只需将堆栈跟踪添加到原始问题中。谢谢你的提示,我自己也发现了。这看起来很奇怪。因为它是间歇性的,你有没有用种族检测器来检测?它是在任一主机上运行客户机/服务器时发生的,还是只以一种方式发生?
goroutine 1 [running]:
runtime.throw(0x1927b8, 0x5)
    /usr/local/go/src/runtime/panic.go:527 +0x90 fp=0xc82004bd78 sp=0xc82004bd60
runtime.sigpanic()
    /usr/local/go/src/runtime/sigpanic_unix.go:27 +0x2ba fp=0xc82004bdc8 sp=0xc82004bd78
main.main()
    /Users/ple/dev/go/src/Peter-test/main.go:108 +0x33c fp=0xc82004bf50 sp=0xc82004bdc8
runtime.main()
    /usr/local/go/src/runtime/proc.go:111 +0x2b0 fp=0xc82004bfa0 sp=0xc82004bf50
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1696 +0x1 fp=0xc82004bfa8 sp=0xc82004bfa0

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1696 +0x1

goroutine 5 [trace reader (blocked)]:
runtime.ReadTrace(0x0, 0x0, 0x0)
    /usr/local/go/src/runtime/trace.go:339 +0x207
runtime/trace.Start.func1(0x5a42e0, 0xc82002a020)
    /usr/local/go/src/runtime/trace/trace.go:28 +0x18
created by runtime/trace.Start
    /usr/local/go/src/runtime/trace/trace.go:34 +0x78

goroutine 6 [runnable]:
reflect.Value.Index(0x1234c0, 0xc8204ac004, 0x51, 0x75, 0x12ac00, 0xc8204ac078, 0x48)
    /usr/local/go/src/reflect/value.go:823
encoding/binary.(*encoder).value(0xc8200475a0, 0x1234c0, 0xc8204ac004, 0x51)
    /usr/local/go/src/encoding/binary/binary.go:509 +0x808
encoding/binary.(*encoder).value(0xc8200475a0, 0x162ba0, 0xc8204ac000, 0x59)
    /usr/local/go/src/encoding/binary/binary.go:518 +0xb4f
encoding/binary.Write(0x621138, 0xc8200a2000, 0x621160, 0x289ef0, 0x162ba0, 0xc8204ac000, 0x0, 0x0)
    /usr/local/go/src/encoding/binary/binary.go:316 +0x1792
main.listener(0x0, 0x1, 0xc82002a020)
    /Users/ple/dev/go/src/Peter-test/main.go:59 +0xac8
created by main.main
    /Users/ple/dev/go/src/Peter-test/main.go:105 +0x332