ListenUDP, a one way street? - go

When I run this code an incoming UDP packet gets read in, however no packet gets sent back out. Why is this? (I verified this fact with wireshark). I want to be able to communicate two ways over a UDP connection, how do I achieve this with golang?
//Node 1
func main() {
addr := net.UDPAddr{
Port: 7000,
IP: net.ParseIP("127.0.0.1"),
}
conn, err := net.ListenUDP("udp", &addr)
defer conn.Close()
if err != nil {
panic(err)
}
for {
b := make([]byte, 10)
conn.Read(b)
fmt.Println(string(b[:]))
conn.Write([]byte("sending back"))
}
}
func main() {
sock, _ := net.Dial("udp", "127.0.0.1:7000")
buf := make([]byte, 10)
sock.Write([]byte("first send"))
sock.Read(buf)
fmt.Println(string(buf[:]))
}

Remember, UDP is connection-less. When you call conn.Write, your listener doesn't know where to send the packet. In your server code, you should be using UDPConn.ReadFromUDP and UDPConn.WriteToUDP to obtain and specify the client address, as mentioned in the documentation:
The returned connection's ReadFrom and WriteTo methods can be used to receive and send UDP packets with per-packet addressing.
Your modified Node 1 loop could then look something like the following:
for {
b := make([]byte, 10)
n, clientAddr, _ := conn.ReadFromUDP(b) // TODO: error check
fmt.Println(string(b[:n]))
conn.WriteToUDP([]byte("sending back"), clientAddr)
}

Related

How to communicate with multiple clients in a UDP server in go?

I have a server that transfers files over UDP and it works well when with only one client at the time, but if other client tries to connect, the following error is thrown
listen udp :20000: bind: Only one usage of each socket address
(protocol/network address/port) is normally permitted.
This is my code in main:
...
fmt.Println("Input the number of connections")
var number int
fmt.Scanln(&number)
var wg sync.WaitGroup
wg.Add(number)
lAdd, err := net.ResolveUDPAddr("udp", PORT)
if err != nil {
fmt.Println(err)
return
}
for i:=0; i < number; i++ {
go startConnection(lAdd, file, i, wg)
}
wg.Wait()
This is the code of startConnection:
func startConnection (lAdd * net.UDPAddr, archivo string, i int, wg sync.WaitGroup) {
defer wg.Done()
conn, err := net.ListenUDP("udp", lAdd)
if err != nil {
logger.Println("There was an error: ", err)
return
}
defer conn.Close()
sendFile (conn, add, archivo, i)
}
A server should call Listen only once to start the listener. At that point, it is listening. This is where TCP and UDP diverge, because of the nature of the protocols.
ListenTCP returns a TCPListener, which can be used to Accept connections as they come in. Each connection can then send and receive data.
ListenUDP returns a UDPConn, the same as DialUDP, because UDP is a connectionless protocol. You just read and write to the UDPConn. UDP packet headers include the source and target information, so you can use ReadFrom to read data and see who sent it, and WriteTo to respond to a specific client.
This article has a pretty thorough rundown of implementing UDP connectivity in Go: https://ops.tips/blog/udp-client-and-server-in-go/

Golang send and receive udp packets simultaneously

I have a little problem. I want to receive and write udp packets with a DialUDP function. The problem is that it only can write and not receive udp packets (i think). How can i send a packet and let the program wait on a respond from the server?
my code:
if programPacketType == "udp"{
server,err := net.ResolveUDPAddr("udp4", programAddressInput)
checkError(err)
lServer, err := net.ResolveUDPAddr("udp4", programLocalAddressInput)
checkError(err)
conn, err := net.DialUDP("udp4", server, lServer)
checkError(err)
i := 0
for {
msg := strconv.Itoa(i)
i++
buf := []byte(msg)
_,err := conn.Write(buf)
if err != nil {
fmt.Println(msg, err)
}
fmt.Println("sended:", i, "to connected server")
time.Sleep(time.Second * 1)
}
}
thanks.
(Pls ignore grammatical mistakes,)

How can I keep reading using net Conn Read method

I'm creating a simple chat server as a personal project to learn net package and some concurrency in go. My 1st idea is to make the server print whatever is send using nc command echo -n "hello" | nc -w1 -4 localhost 2016 -p 61865. However after the 1st read my code ignores the subsequent messages.
func (s *Server) messageReader(conn net.Conn) {
defer conn.Close()
buffer := make([]byte, 1024)
for {
//read buff
blen, err := conn.Read(buffer)
if err != nil {
log.Fatal(err)
}
message := string(buffer[:blen])
if message == "/quit" {
fmt.Println("quit command received. Bye.")
return
}
if blen > 0 {
fmt.Println(message)
buffer = buffer[:0]
}
}
}
// Run Start up the server. Manages join and leave chat
func (s *Server) Run() {
// Listen on port TCP 2016
listener, err := net.Listen("tcp", ":2016")
if err != nil {
log.Fatal(err)
}
defer listener.Close()
for {
//wait for connection
conn, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
go s.messageReader(conn)
}
}
If I send a new message from a new client it prints without problems but if I send another one it does nothing. What am I missing do I need to reset the Conn or close it and spawn a new one?
After printing your message, you slice buffer down to zero length. You can't read any data into a zero-length slice. There's no reason to re-slice your read buffer at all.
You also need to handle the read bytes before checking for errors, as io.EOF can be returned on a successful read.
You shouldn't use log.Fatal in the server's read loop, as that calls os.Exit
A working messageReader body might look like:
defer conn.Close()
buffer := make([]byte, 1024)
for {
n, err := conn.Read(buffer)
message := string(buffer[:n])
if message == "/quit" {
fmt.Println("quit command received. Bye.")
return
}
if n > 0 {
fmt.Println(message)
}
if err != nil {
log.Println(err)
return
}
}
You should note though that because you're not using any sort of framing protocol here, you can't guarantee that each conn.Read returns a complete or single message. You need to have some sort of higher-level protocol to delimit messages in your stream.

Can't read UDP reply (golang)

I'm working on a Go program that sends out a UDP broadcast to query existence of devices on the local network and then reads the replies. Using Wireshark I confirm that the packet is broadcast and that the single device on (my) network replies (ten times, in fact) but my application blocks on the read as if it does not see the incoming packet. Here is the code:
func Discover(timeout int) ([]string, error) {
inBuf := make([]byte, 1024)
devices := make([]string, 0)
var readLen int
var fromAddr *net.UDPAddr
// get server connection
server := fmt.Sprintf("%s:%d", bcastIP, udpDiscoverPort) // "255.255.255.255", 10000
serverAddr, err = net.ResolveUDPAddr("udp", server)
checkErr(err)
ourAddr, err = net.ResolveUDPAddr("udp", "192.168.1.132:10000")
checkErr(err)
conn, err = net.DialUDP("udp", ourAddr, serverAddr)
checkErr(err)
defer conn.Close()
// send the Discover message
discoverMsg := []byte(magic)
discoverMsg = append(discoverMsg, discovery...)
sendLen, err := conn.Write(discoverMsg)
checkErr(err)
fmt.Println("Sent", sendLen, "bytes")
// read one reply
readLen, fromAddr, err = conn.ReadFromUDP(inBuf)
fmt.Println("Read ", readLen, "bytesfrom ", fromAddr)
txtutil.Dump(string(inBuf[:readLen]))
return devices, nil
}
checkErr(err) prints a diagnostic and exits if err is not nil, BTW.
The information in the replies looks like:
Internet Protocol Version 4, Src: 192.168.1.126 (192.168.1.126), Dst: 192.168.1.132 (192.168.1.132)
User Datagram Protocol, Src Port: ndmp (10000), Dst Port: ndmp (10000)
I have tried "0.0.0.0:10000", ":10000" and "127.0.0.1:10000" in place of "192.168.1.132:10000" and none seem to make any difference.
Any suggestions as to what I'm doing wrong are welcome!
You need to use ListenUDP instead of DialUDP. When you use DialUDP, it creates a "connected" UDP port, and only packets originating from the remote address are returned on read.
conn, err = net.ListenUDP("udp", ourAddr)
Since the connection doesn't have a default destination, you will also need to use WriteTo* methods to send packets:
sendLen, err := conn.WriteToUDP(discoverMsg, serverAddr)

Client/Server using UDP in Go

I'm using gob to send messages from client to serve and this is working, however when the server response to client this don't read from connection.
func servidor(porta int){
var site string
addr := net.UDPAddr{
Port: porta,
IP: net.ParseIP("localhost"),
}
conn, erro := net.ListenUDP("udp", &addr)
verificaErro(erro)
enc := gob.NewEncoder(conn)
dec := gob.NewDecoder(conn)
dec.Decode(&site)
enc.Encode(site)
}
func cliente(site string){
porta := "1200"
conn := ConnectToSocket("localhost:"+porta)
enc := gob.NewEncoder(conn)
dec := gob.NewDecoder(conn)
enc.Encode("Test")
dec.Decode(&site)
fmt.Println(site)
}
How can I solve this problem?
There are two issues:
UDP is a packet based protocol, but gob is expecting a stream. The encoder can call the connection Write method multiple times when encoding a value. Each write sends a packet. You probably want one packet per encoded value.
Gob streams have state. The encoder sends information about any type once and expects the decoder to remember the information. Even if the gob encoder calls Write exactly once per encoded value, packets sent by subsequent writes will not include the type information.
The fix is to encode to a buffer and send that buffer:
var buf Bytes.Buffer
if err := gob.NewEncoder(&buf).Encode(value); err != nil {
// handle error
}
_, err := c.WriteTo(buf.Bytes(), addr)
Receive to a buffer and decode from that buffer:
buf := make([]byte, 1024)
n, addr, err := c.ReadFrom(buf)
if err != nil {
// handle error
}
if err := gob.NewDecoder(bytes.NewReader(buf[:n])).Decode(&v); err != nil {
// handle error
}

Resources