How to tell net.Conn is disconnected in client side code?

3,647 views
Skip to first unread message

dlin

unread,
May 27, 2013, 9:28:09 PM5/27/13
to golan...@googlegroups.com
I'm trying to recover a disconnected situation on client side.  But I can not handle it well.

1. I can not check connection property to make sure should I Close()

if ! c.Closed() {  // There is no Closed() function 
  c.Close()
}

2. Is there faster method (eg. just call c.Write() to write block of struct memory?)


// client code. If write failed, it will redial after 5 second
package main

import (
"encoding/binary"
"log"
"net"
"time"
)

const someTime = 5 * time.Second

type IP4Addr struct {
IP   [4]byte
Port uint16
}
type Command struct {
IP4Addr
CliConnSeq, SrvConnSeq uint32
Id                     uint32 // srvId*100 + proxyId*10 + cliId
Seq                    uint32 // srvSeq*10000 + cliSeq
}

func main() {
var dummy Command
L_DIAL:
for {
log.Println("Dialing")
c, err := net.Dial("tcp", ":20000")
if err != nil {
log.Println(err)
time.Sleep(someTime)
continue
}
for {
err = binary.Write(c, binary.LittleEndian, dummy)
if err != nil {
log.Println(err)
time.Sleep(someTime)
continue L_DIAL
}
err = binary.Read(c, binary.LittleEndian, &dummy)
if err != nil {
log.Println(err)
time.Sleep(someTime)
continue L_DIAL
}
time.Sleep(time.Second)
}
}
}

Dave Cheney

unread,
May 27, 2013, 9:30:46 PM5/27/13
to dlin, golang-nuts
This has been discussed several times on the mailing list, I suggest
you search the archives. The summary is, you cannot tell if someone
has closed the connection without doing a Read or Write call and
responding to the error status.
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

dlin

unread,
May 27, 2013, 9:45:11 PM5/27/13
to golan...@googlegroups.com, dlin
So, maybe one solution is writing a wrapper by myself?

type MyConn struct {
  net.Conn
  opened bool
}
func (c *MyConn )Dial(...) {
  c.Conn.Dial(...)
   opened = true  // if not err
}
func (c *MyConn )Close(...) {
  c.Conn.Close(...)
  opened = false 
}
func (c *MyConn )Write(...) {
  c.Conn.Write(...)
  if err {
    c.Close()
  } 
}
func (c *MyConn )Read(...) {
  c.Conn.Read(...)
  if err {
    c.Close()
  }
}

Dave Cheney

unread,
May 27, 2013, 9:46:36 PM5/27/13
to dlin, golang-nuts
Can you please describe the problem you are solving, not the solution
you have come up with.

dlin

unread,
May 27, 2013, 10:04:46 PM5/27/13
to golan...@googlegroups.com, dlin
I'm sorry I can not explain the question well.  So, I try to use code to explain.

My problem is: I'm trying to implement a async protocol, one goroutine for Read, one goroutine for Write.
When client try to Write()/Read() but fail,  I'll return back to the main goroutine.
If I don't know the status of Connection maybe one of the goroutine may hang forever.
for example, sendCmdsToSrv call Write() and failed, it quit.  But recvCmdsFromSrv() may still waiting response. So the WaitGroup  still waiting.

func srvService(srvAddr string) chan<- Command {
c := make(chan Command, *maxCommands)
go func(c chan Command) {
for srvConnSeq := uint32(0); ; srvConnSeq++ {
err := dialServer(srvConnSeq, &srvConn, srvAddr)
if err != nil {
break
}
var wg sync.WaitGroup
wg.Add(2)
go func() {
sendCmdsToSrv(srvConn, srvConnSeq, c)
wg.Done()
}()
go func() {
recvCmdsFromSrv(srvConn, srvConnSeq, c)
wg.Done()
}()
wg.Wait()
}
}(c)
return c
}

Dave Cheney

unread,
May 27, 2013, 10:32:07 PM5/27/13
to dlin, golan...@googlegroups.com, dlin
If you close the socket all reads and writes waiting will return io.EOF. 

dlin

unread,
May 28, 2013, 7:28:38 AM5/28/13
to golan...@googlegroups.com, dlin
In my previous code. There are two goroutines.
One for send to net.Conn.
Another for recv from net.Conn.

If one Close() the net.Conn  will that cause 'data race' problem?

Dave Cheney

unread,
May 28, 2013, 7:33:52 AM5/28/13
to dlin, golan...@googlegroups.com, dlin
No, not for net.Conn.Close(), multiple closers are expected and catered for. If you wrap the net.Conn in another type, no such guarantee exists. 


André Moraes

unread,
May 28, 2013, 7:56:32 AM5/28/13
to dlin, golan...@googlegroups.com
On Tue, May 28, 2013 at 8:28 AM, dlin <dli...@gmail.com> wrote:
> In my previous code. There are two goroutines.
> One for send to net.Conn.
> Another for recv from net.Conn.

This talk could give you some help, the problem is similar

http://www.youtube.com/watch?v=QDDwwePbDtw


--
André Moraes
http://amoraes.info
Reply all
Reply to author
Forward
0 new messages