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

Comments

Projects
None yet
5 participants
@gopherbot
Copy link

commented Jun 16, 2012

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

This comment has been minimized.

Copy link
Member

commented Jun 22, 2012

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

This comment has been minimized.

Copy link
Author

commented Jun 27, 2012

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

This comment has been minimized.

Copy link
Author

commented Jul 2, 2012

Comment 3 by support@ryron.org:

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

This comment has been minimized.

Copy link
Contributor

commented Sep 12, 2012

Comment 4:

I swear we have a bug for this somewhere.

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

@rsc

This comment has been minimized.

Copy link
Contributor

commented Sep 12, 2012

Comment 5:

Labels changed: added go1.1.

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Oct 11, 2012

Comment 6:

http://golang.org/cl/6604072

Owner changed to @alexbrainman.

Status changed to Started.

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Oct 30, 2012

Comment 7:

This issue was closed by revision fa3e4fc.

Status changed to Fixed.

@gopherbot

This comment has been minimized.

Copy link
Author

commented Jun 24, 2013

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

This comment has been minimized.

Copy link
Contributor

commented Jun 24, 2013

Comment 9:

Please open a new issue.
@chai2010

This comment has been minimized.

Copy link
Contributor

commented Jun 24, 2013

Comment 10:

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

This comment has been minimized.

Copy link
Contributor

commented Jun 24, 2013

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.
You can’t perform that action at this time.