I can not send multicast request to LAN from Go on Win10.
I have Windows 10 1909.
I am running wireshark with filter host 239.255.255.250 or host 172.19.21.116 or port 1982 where .116 is IP of device I am looking for.
I have YeeLight UWP app installed
I have this code (removed every if err != nil):
package main
import (
"bytes"
"net"
"time"
)
func main() {
bulbMulticastAddr := &net.UDPAddr{IP: net.IPv4(239, 255, 255, 250), Port: 1982}
bulbSearchRequest := new(bytes.Buffer)
_, err := bulbSearchRequest.WriteString("M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1982\r\nMAN:\"ssdp:discover\"\r\nST:wifi_bulb\r\n")
conn, err := net.ListenUDP("udp4", bulbMulticastAddr)
conn.WriteTo(bulbSearchRequest.Bytes(), bulbMulticastAddr)
time.Sleep(time.Duration(6) * time.Second)
}
When I run go run myapp, in WireShark I see single UDP packet with source 127.0.0.1 and destination 239.255.255.250
When I run Yeelight UWP app, in WireShark I see in WireShark two same packets: one using Ethernet interface and one using loopback.
And after some time OS works (few hours - different apps are running), it starts working.
When I use
iflist, _ := net.Interfaces() // iflist[0] is Ethernet
conn, err := net.ListenMulticastUDP("udp4", &iflist[0], bulbMulticastAddr)
conn.WriteTo(bulbSearchRequest.Bytes(), bulbMulticastAddr)
Everything goes right
What am I doing wrong? Each tutorial about multicast shows the way I am doing is right, but it does not work as expected. I am missing something?
Why ListenUDP() not working as expected?
go version go1.14 windows/amd64
Related
I am not able to manage the wireguard interface using wgctl on Windows (10). I have used it on linux and all is fine. I'm using Windows 10 latest updates, wireguard.exe latest, go 1.17.3 latest.
I am using a tunnel created with wireguard.exe /installtunnelservice /path/wg0.conf. If I manage the tunnel with the wireguard GUI, it all works fine. But I need to do it programatically.
C:\>wg
interface: wg0
public key: K0BZ3Bk...5tCWo=
private key: (hidden)
listening port: 57538
peer: 7W6tOXI...F7zAo=
endpoint: 159....105:51820
allowed ips: 100.127.128.0/18
latest handshake: 43 seconds ago
transfer: 31.61 KiB received, 115.69 KiB sent
persistent keepalive: every 25 seconds
...
The following code exits with "file does not exist". Having stepped the code into the library, I think that wireguard.exe is using NT Kernel mode and the library does not support it? Can someone please confirm? What is the best way around this?
package main
import (
"log"
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
func main() {
wgc, err := wgctrl.New()
if err != nil {
log.Printf("wgctrl.New: %s", err)
}
defer wgc.Close()
cfg := wgtypes.Config{}
port := 51822
cfg.ListenPort = &port
err = wgc.ConfigureDevice("wg0", cfg)
if err != nil {
log.Printf("wgc.ConfigureDevice: %s", err)
}
}
After escalating the issue on GitHub, it turned out to be a bug in the library which was promptly fixed not long after I posted this.
I am building a tcp socket server in golang. It works well with less than ~140 client connection. But if i try to set max connection number to 500, after 140th clients do not connect to the server.
I increased file descriptor count to 1048576 but it does not still work.
$ulimit -n
1048576
I think the problem comes from operation system.(server and clients work on same machine) So OS information:
Mac OS 10.12 Sierra 64 bit.
Does anyone have any idea why i can't increase tcp connection number?
github
I am on the same operating system as you, but I could not reproduce your issue. I am using Go version 1.7.4. I have not tested on Go 1.8, but it was released earlier today.
I created two files, server.go and client.go (reproduced below). When I run them, I get way more than 140 connections. Before running, I switched to root and setup the ulimit like so:
$ sudo -s
$ ulimit -n 10000
The client outputs:
Established 1 connections
...
Established 2971 connections
panic: dial tcp 127.0.0.1:1337: socket: too many open files in system
The server outputs something very similar.
Here is client.go:
package main
import (
"fmt"
"net"
)
func main() {
var numConns int
for {
_, err := net.Dial("tcp", "127.0.0.1:1337")
if err != nil {
panic(err)
}
numConns++
fmt.Println("Established", numConns, "connections")
}
}
And server.go:
package main
import (
"fmt"
"net"
)
func main() {
listener, err := net.Listen("tcp", ":1337")
if err != nil {
panic(err)
}
var numConns int
for {
_, err := listener.Accept()
if err != nil {
panic(err)
}
numConns++
fmt.Println("Got", numConns, "connections")
}
}
This is not a problem with the operating system, but the hardware. It is likely a problem with your router. Commercial routers do tend to fail when you get into that range. My guess is that Alex is testing at a large company or university where they have commercial grade routers, but you are testing at home.
How can you ping an IP address from a golang application? The ultimate goal is to check if a server is online.
Does go have a way in the standard library to implement a network ping?
As #desaipath mentions, there is no way to do this in the standard library. However, you do not need to write the code for yourself - it has already been done:
https://github.com/tatsushid/go-fastping
Note, sending ICMP packets requires root privileges
I needed the same thing as you and I've made a workaround (with exec.Command) for my Raspberry Pi to check if servers are online. Here is the experimental code
out, _ := exec.Command("ping", "192.168.0.111", "-c 5", "-i 3", "-w 10").Output()
if strings.Contains(string(out), "Destination Host Unreachable") {
fmt.Println("TANGO DOWN")
} else {
fmt.Println("IT'S ALIVEEE")
}
#jpillora's answer suggests using go-fastping, but that library hasn't been updated since Jan 8, 2016. It may not be an issue as the logic of pinging is quite simple, but if you want a more recent package then there's go-ping.
Although not a real ICMP ping, this is what use to probe my servers using the TCP protocol:
host := "example.com"
port := "80"
timeout := time.Duration(1 * time.Second)
_, err := net.DialTimeout("tcp", host+":"+port, timeout)
if err != nil {
fmt.Printf("%s %s %s\n", host, "not responding", err.Error())
} else {
fmt.Printf("%s %s %s\n", host, "responding on port:", port)
}
No.
Go does not have any built-in way to ping a server in standard library.
You need to write code by yourself.
For that, you can look into icmp section of golang library. And use this list of control messages, to construct icmp message properly.
But, keep in mind that some server administrator shuts down ping service on their server, for security reason. So, If your goal is to ultimately check if server is online or not, this is not 100% reliable method.
package main
import (
"fmt"
"os/exec"
)
func main() {
Command := fmt.Sprintf("ping -c 1 10.2.201.174 > /dev/null && echo true || echo false")
output, err := exec.Command("/bin/sh", "-c", Command).Output()
fmt.Print(string(output))
fmt.Print(err)
}
My binary takes a port parameter and starts a http server. If pass a 0 to the -port, it will find a free port and start on it.
After this, how do I find which port is this if I have the command object with me and can get the process id? I am trying to write my application in golang. I am also curious how this is done in general.
It's OS specific, but on linux you can do
netstat -npl
that will list which programs are listening on which ports
If you just want to print it out from your app, you can use the alternative form of starting the http server by creating your own tcp listener and then call http.Serve
example:
package main
import (
"fmt"
"net"
"net/http"
"os"
)
func main() {
lsnr, err := net.Listen("tcp", ":0")
if err != nil {
fmt.Println("Error listening:", err)
os.Exit(1)
}
fmt.Println("Listening on:", lsnr.Addr())
err = http.Serve(lsnr, nil)
fmt.Println("Server exited with:", err)
os.Exit(1)
}
outputs:
Listening on: [::]:53939
package main
import (
"fmt"
"net"
)
func main() {
var localaddr net.TCPAddr
var remoteaddr net.TCPAddr
localaddr.IP = net.ParseIP("192.168.1.104")
localaddr.Port = 6000
remoteaddr.IP = net.ParseIP("192.168.1.104")
remoteaddr.Port = 5000
if localaddr.IP == nil || remoteaddr.IP == nil {
fmt.Println("error")
}
if _, err := net.DialTCP("tcp", &localaddr, &remoteaddr); err != nil {
fmt.Println(err)
}
fmt.Println("End")
}
If the function specify local IP address, it always reports a run time error "dial tcp 192.168.1.104:5000: An invalid argument was supplied." I'm confused, should it always be a nil for local IP address ?
go version : 1.1 Beta
OS: Win7 64bit
Tried in go 1.0.3, it seemed OK
Go's net package, like most such implementations, recognizes port-only syntax for connecting to localhost:
:5000
is equivalent to
<my-ip-address>:5000
Thus, you can do:
net.Dial("tcp", ":5000")
No, it is ok to have laddr argument specified in DialTCP. The problem is that the specified port (6000) is outside of default Win7 dynamic port range and couldn't be used for outgoing connection. It works on Linux and Mac, actually (if you don't forget to change the IP address to one of your own system).