golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.06k stars 17.68k forks source link

net: cannot send multicast using ListenPacket("udp4", "") on Windows 10 (1909) #37998

Open filimonic opened 4 years ago

filimonic commented 4 years ago

What version of Go are you using (go version)?

go version go1.14.1 windows/amd64

Does this issue reproduce with the latest release?

Yes, with 1.14 and 1.14.1 ( never tested earlier )

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\ADFilimonov\AppData\Local\go-build
set GOENV=C:\Users\ADFilimonov\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\ADFilimonov\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=c:\go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=c:\go\pkg\tool\windows_amd64
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\ADFILI~1\AppData\Local\Temp\go-build411155850=/tmp/go-build -gno-record-gcc-switches

What did you do?

Single file in directory: mctest_test.go :

package mctest

import (
    "net"
    "testing"
    "time"
)

var (
    bulbMulticastAddr *net.UDPAddr   = &net.UDPAddr{IP: net.IPv4(239, 255, 255, 250), Port: 1982}
    bulbSearchRequest []byte         = []byte("M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1982\r\nMAN:\"ssdp:discover\"\r\nST:wifi_bulb\r\n")
    bulbSearchConn    net.PacketConn = nil
)

func TestMC(t *testing.T) {
    testMulticast(5)
}

func testMulticast(timeout int) error {
    bulbSearchConn, err := net.ListenPacket("udp4", "")
    if err != nil {
        return err
    }

    readDeadlineTime := time.Now().Add(time.Second * time.Duration(timeout))
    err = bulbSearchConn.SetReadDeadline(readDeadlineTime)
    if err != nil {
        return err
    }

    _, err = bulbSearchConn.WriteTo(bulbSearchRequest, bulbMulticastAddr)
    if err != nil {
        return err
    }

    time.Sleep(time.Second * time.Duration(10))
    return nil
}
  1. I run Wireshark on two interfaces ( "Ethernet" and "Adapter for loopback traffic capture" ) with filter udp port 1982.
  2. I run code
    CD /D S:\PRJ\doesntmatter\pkg\mctest
    go test
  3. I monitor packets wireshark shows.

What did you expect to see?

Expected 2 packets with source = "ip-of-my-ethernet", target "mulicast address", one using Ethernet interface and one using loopback interface

What did you see instead?

Sometimes everything is right ( I see everything as expected ). And sometimes I see 1 packet with source = "127.0.0.1", target "mulicast address", using loopback interface.

I can not determine, what happens with my envinronment to "switch" this behaviour. After system reboot I can see it working and some time after it stops, ot vice-versa.

SCREENSHOTS

Wireshark setup

WSCAP_SETUP

Wireshark shows OK

WSCAP_WHEN_OK

Wireshark shows NOT OK

Sorry I have no screenshot now. It happens periodically each few days. I try add later Update: Added Screenshot image

andybons commented 4 years ago

@mikioh @bradfitz @ianlancetaylor

andybons commented 4 years ago

@alexbrainman

filimonic commented 4 years ago

Added screenshot. On today morning, same code fails.

alexbrainman commented 4 years ago

@filimonic sorry I am not network person, so I do not know why your program does not work reliably. I also don't have Wireshark program installed on my computer, so I cannot even try to reproduce your problem.

But I noticed there are some tests in net package (in %GOROOT%\src\net directory), that call ListenPacket

$ git grep -e ListenPacket.*udp4 -n
mockserver_test.go:337:                 return ListenPacket("udp4", "127.0.0.1:0
mockserver_test.go:344:                 return ListenPacket("udp4", "127.0.0.1:0
$

All tests in net are obviously succeed on everyone's Windows computers. Maybe you can use net test code and adjust it to make it do what you need?

Alex

iwdgo commented 4 years ago

@alexbrainman The listed tests are skipped for Windows because the function used (fd *netFD) dup() is not implemented. It seems that there is no relevant test of UDP on Windows.

@filimonic There are several posts about conflicts between RDP and UDP on 1909. It might be the cause of what is identified.

iwdgo commented 4 years ago

Here are the relevant tests for UDP on Windows. All successful on 1909. Microsoft Windows [Version 10.0.18363.836]

$GOPATH\golang\go\src>go test -run=".*UDP.*" -v net
=== RUN   TestUDPListener
--- PASS: TestUDPListener (0.01s)
=== RUN   TestDualStackUDPListener
--- PASS: TestDualStackUDPListener (0.01s)
=== RUN   TestUDPConnSpecificMethods
    TestUDPConnSpecificMethods: protoconn_test.go:151: file udp4 127.0.0.1:50157: not supported by windows
--- PASS: TestUDPConnSpecificMethods (0.01s)
=== RUN   TestUDPServer
--- PASS: TestUDPServer (0.04s)
=== RUN   TestResolveUDPAddr
--- PASS: TestResolveUDPAddr (0.02s)
=== RUN   TestWriteToUDP
--- PASS: TestWriteToUDP (0.00s)
=== RUN   TestUDPConnLocalName
--- PASS: TestUDPConnLocalName (0.00s)
=== RUN   TestUDPConnLocalAndRemoteNames
--- PASS: TestUDPConnLocalAndRemoteNames (0.00s)
=== RUN   TestIPv6LinkLocalUnicastUDP
--- PASS: TestIPv6LinkLocalUnicastUDP (0.00s)
=== RUN   TestUDPZeroBytePayload
--- PASS: TestUDPZeroBytePayload (0.00s)
=== RUN   TestUDPZeroByteBuffer
--- PASS: TestUDPZeroByteBuffer (0.00s)
=== RUN   TestUDPReadSizeError
--- PASS: TestUDPReadSizeError (0.00s)
PASS
Socket statistical information:
(inet6, datagram, default): opened=93 connected=1 listened=0 accepted=0 closed=93 openfailed=0 connectfailed=0 listenfailed=0 acceptfailed=0 closefailed=0
(inet4, datagram, default): opened=76 connected=5 listened=0 accepted=0 closed=76 openfailed=0 connectfailed=0 listenfailed=0 acceptfailed=0 closefailed=0
alexbrainman commented 4 years ago

@alexbrainman The listed tests are skipped for Windows because the function used (fd *netFD) dup() is not implemented. It seems that there is no relevant test of UDP on Windows.

Fair enough. Thank you for explaining.

Alex

markwinds commented 1 year ago

I had the same problem, has the problem been solved?