0

I would like to initiate TCP connections between a process and other processes which are already listening from incoming TCP connections. I would like to use the same source address (ip-port) for these connections. I am programming in Go.

I tried to run this code, but the second DialTCP call fails.

func main() {

    ourAddr, _ := net.ResolveTCPAddr("tcp", "localhost:51234")

    otherAddr1, _ := net.ResolveTCPAddr("tcp", "localhost:51236")
    otherAddr2, _ := net.ResolveTCPAddr("tcp", "localhost:51237")

    conn1, err1 := net.DialTCP("tcp", ourAddr, otherAddr1)
    if err1 != nil {
        log.Fatal("err1: " + err1.Error())
    }
    defer conn1.Close()

    conn2, err2 := net.DialTCP("tcp", ourAddr, otherAddr2) // <- this fails
    if err2 != nil {
        log.Fatal("err2: " + err2.Error())
    }
    defer conn2.Close()

}

The error message is: err2: dial tcp 127.0.0.1:51234->127.0.0.1:51237: bind: address already in use

(the problem should not be related to the destination processes since two instances of netcat are already listening on the destination addresses)

I also tried using other ports (in case they were still in use) and it failed the same way

Here is my go version: go version go1.13.4 linux/amd64

It seems to me the problem is not related to TCP but to the way I am using the Go library. What am I doing wrong, and how am I supposed to do?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
niko
  • 71
  • 1
  • 5
  • 1
    https://github.com/libp2p/go-reuseport might help – Steffen Ullrich Nov 23 '19 at 20:00
  • This should be possible in TCP in theory but it isn't in practice, because at the C level `bind()` precedes `connect()`. You can't rely on this kind f thing. – user207421 Nov 23 '19 at 21:06
  • The approach proposed by @SteffenUllrich appears to be what you are looking for. It uses `SO_REUSEADDR` and `SO_REUSEPORT` socket options. It is important to note that these options are not standardized. From their description, it appears they are used in some very load intensive situations and I wonder if go routines mitigate some of the problems they are solving. – Momchil Atanasov Nov 24 '19 at 11:50
  • The approach proposed by Steffen Ullrich will not work with TCP under any circumstances, for the reason I stated. @MomchilAtanasov – user207421 Nov 25 '19 at 09:13

1 Answers1

-1

The problem you are facing is a general one, not related to Go programming language.

To my knowedge, you should not be able to connect to two destinations from the same source IP address and Port. I am pretty sure this is backed up by the message you get.

err2: dial tcp 127.0.0.1:51234->127.0.0.1:51237: bind: address already in use

It is not complaining about your destination address. It is complaining about the source address 127.0.0.1:51234. Try to change your source address and see what happens.


Edit: It appears that there are socket options SO_REUSEADDR and SO_REUSEPORT that allow that but are non-standardized and appear to be used under verify specific load-intensive scenarios.

It would help to know why you want to achieve such a setup.


Addition: There is a stackoverflow question that is related to your problem: TCP: can two different sockets share a port?

Momchil Atanasov
  • 479
  • 4
  • 10
  • The interleaved data you describe cannot possibly occur. – user207421 Nov 24 '19 at 08:55
  • 1
    @user207421, care to explain a bit? What I was describing was a hypothetical problem if a streaming API were to receive from two streams. In what way is that not possible, buffer size and TCP aside? – Momchil Atanasov Nov 24 '19 at 11:09