Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: problem with Close and final packet delivery #3746

Closed
gopherbot opened this issue Jun 16, 2012 · 11 comments
Closed

net: problem with Close and final packet delivery #3746

gopherbot opened this issue Jun 16, 2012 · 11 comments
Milestone

Comments

@gopherbot
Copy link

by feixings:

latest version of Go:1.0.1 、1.0.2
What steps will reproduce the problem?
1.cd C:\Go\src\pkg\net\rpc\jsonrpc
2.go test

What is the expected output?
test no pass

What do you see instead?
rpc:server cannot decode request

Which compiler are you using (5g, 6g, 8g, gccgo)?
8g

Which operating system are you using?
windows 7

Which version are you using?  (run 'go version')
1.0.2

Please provide any additional information below.
/**
* ArithClient
 */

package main

import (
    "net/rpc"
    "fmt"
    "log"
)

type Args struct {
    A, B int
}

type Quotient struct {
    Quo, Rem int
}

func main() {

    client, err := rpc.DialHTTP("tcp", "127.0.0.1:1234")
    if err != nil {
        log.Fatal("dialing:", err)
    }
    // Synchronous call
    args := Args{17, 8}
    var reply int
    err = client.Call("Arith.Multiply", args, &reply)
    if err != nil {
        log.Fatal("arith error:", err)
    }
    fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)

    var quot Quotient
    err = client.Call("Arith.Divide", args, &quot)
    if err != nil {
        log.Fatal("arith error:", err)
    }
    fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)

}

/**
* ArithServer
 */

package main

import (
    "fmt"
    "net/rpc"
    "errors"
    "net/http"
)

type Args struct {
    A, B int
}

type Quotient struct {
    Quo, Rem int
}

type Arith int

func (t *Arith) Multiply(args *Args, reply *int) error {
    *reply = args.A * args.B
    return nil
}

func (t *Arith) Divide(args *Args, quo *Quotient) error {
    if args.B == 0 {
        return errors.New("divide by zero")
    }
    quo.Quo = args.A / args.B
    quo.Rem = args.A % args.B
    return nil
}

func main() {

    arith := new(Arith)
    rpc.Register(arith)
    rpc.HandleHTTP()

    err := http.ListenAndServe(":1234", nil)
    if err != nil {
        fmt.Println(err.Error())
    }
}

run result:

rpc:server cannot decode request:WSARecv tcp 127.0.0.1:1234:The specified network name
is no langer available.

Attachments:

  1. rpc-demo.zip (1126 bytes)
@alexbrainman
Copy link
Member

Comment 1:

Here is even simpler program to demonstrate your issue:
package rpc
import (
    "net/http"
    "net"
    "testing"
)
func TestALEX(t *testing.T) {
    arith := new(Arith)
    Register(arith)
    HandleHTTP()
    l, e := net.Listen("tcp", "127.0.0.1:0")
    if e != nil {
        t.Fatalf("listen error: %v", e)
    }
    defer l.Close()
    go http.Serve(l, nil)
    client, err := DialHTTP("tcp", l.Addr().String())
    if err != nil {
        t.Fatalf("dialing: %v", err)
    }
    defer client.Close()
    args := Args{17, 8}
    var reply Reply
    err = client.Call("Arith.Mul", args, &reply)
    if err != nil {
        t.Fatal("arith error:", err)
    }
    t.Logf("Arith: %d*%d=%d\n", args.A, args.B, reply)
}
I think the problem here is, we do not use tcp as intended. Here is pure net test to
demonstrate what is happening:
package net
import (
    "io"
    "testing"
    "time"
)
func TestALEX(t *testing.T) {
    l, e := Listen("tcp", "127.0.0.1:0")
    if e != nil {
        t.Fatal(e)
    }
    defer l.Close()
    read := func(r io.Reader) (byte, error) {
        var m [1]byte
        _, e = io.ReadFull(r, m[:])
        return m[0], e
    }
    write := func(w io.Writer, m byte) {
        _, e = w.Write([]byte{m})
        if e != nil {
            t.Fatal(e)
        }
    }
    ch := make(chan error)
    go func() {
        c, e := l.Accept()
        if e != nil {
            t.Fatal(e)
        }
        defer c.Close()
        for e == nil {
            _, e = read(c)
        }
        ch <- e
    }()
    c, err := Dial("tcp", l.Addr().String())
    if err != nil {
        t.Fatal(e)
    }
    write(c, 'A')
    go read(c)
    time.Sleep(10 * time.Millisecond)
    c.Close()
    e = <-ch
    if e != nil && e != io.EOF {
        t.Fatal(e)
    }
}
This test fails because tcp connection is reset by c.Close. We should really use
c.(*TCPConn).CloseWrite() instead. But we do not. In net/rpc and in net/http/fcgi
(https://golang.org/issue/3710) we assume that tcp connection can
just be closed and final bits of conversation will reach their destination reliably. But
here we see connection is reset, so tcp peers are out of sync and confused.
We could change our windows network code to ignore these read errors - rewrite this
error code into io.EOF, but I am not sure if this is always appropriate. This suggestion
will not help when we hurt other programs, like in
https://golang.org/issue/3710.
I am not sure what to do.
Alex

Status changed to Accepted.

@gopherbot
Copy link
Author

Comment 2 by feixings:

Sometimes Occur this errors:
AcceptEx failed.The specified network name is no longer available.
i think the sockets on windows is not stable.

@gopherbot
Copy link
Author

Comment 3 by support@ryron.org:

and can not connect to other device. both writing by golang

@rsc
Copy link
Contributor

rsc commented Sep 12, 2012

Comment 4:

I swear we have a bug for this somewhere.

Labels changed: added priority-soon, removed priority-triage.

@rsc
Copy link
Contributor

rsc commented Sep 12, 2012

Comment 5:

Labels changed: added go1.1.

@alexbrainman
Copy link
Member

Comment 6:

http://golang.org/cl/6604072

Owner changed to @alexbrainman.

Status changed to Started.

@alexbrainman
Copy link
Member

Comment 7:

This issue was closed by revision fa3e4fc.

Status changed to Fixed.

@gopherbot
Copy link
Author

Comment 8 by yodamgod:

I've done a same tutorial he did. but the problem is not fixed, yet.
You can see the RPC tutorial here.
http://jan.newmarch.name/go/rpc/chapter-rpc.html
I had exactly a same error as he'd written before.
rpc: rpc: server cannot decode request: WSARecv tcp 127.0.0.1:1234: The specified
network name is no longer available.

Attachments:

  1. Screenshot - 2013-06-24 , 오후 9_29_37.png (17897 bytes)
  2. Screenshot - 2013-06-24 , 오후 9_29_47.png (9563 bytes)

@davecheney
Copy link
Contributor

Comment 9:

Please open a new issue.

@chai2010
Copy link
Contributor

Comment 10:

Test test program seems has a issue: the rpc client need call client.Close() when the
program exit.

@chai2010
Copy link
Contributor

Comment 11:

The test program seems has a issue: the rpc client need call client.Close() when the
program exit.

@rsc rsc added this to the Go1.1 milestone Apr 14, 2015
@rsc rsc removed the go1.1 label Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants