UDP help

314 views
Skip to first unread message

boghi...@gmail.com

unread,
Sep 11, 2014, 12:44:49 PM9/11/14
to golan...@googlegroups.com
So, I need to write an UDP Server/Client in Go. So far it's either been nothing or 100% CPU hogging resulting in death. Here's part of my client code:
addr := net.UDPAddr{
        Port: 2000,
        IP: net.ParseIP("127.0.0.1"),
    }
conn, _ := net.DialUDP("udp", nil, &addr)
var buff bytes.Buffer
buff.ReadFrom(conn)
fmt.Println(string(buff.Bytes()))

and the server:
addr := net.UDPAddr{
        Port: 2000,
        IP: net.ParseIP("127.0.0.1"),
    }
    conn, err := net.ListenUDP("udp", &addr)
    defer conn.Close()
    if err != nil {
        panic(err)
    }
    var buf [1024]byte
    for {
    conn.ReadFromUDP(buf[:])
    conn.Write([]byte("OK"))
conn.Close()
}

It should go like this: client connects server responds with OK. I've added the ReadFromUDP because otherwise it's CPU death by gopher :) This is my first time writing an UDP client/server program.


Mikio Hara

unread,
Sep 12, 2014, 10:55:29 AM9/12/14
to boghi...@gmail.com, golang-nuts
On Fri, Sep 12, 2014 at 1:44 AM, <boghi...@gmail.com> wrote:

> conn, _ := net.DialUDP("udp", nil, &addr)
> var buff bytes.Buffer
> buff.ReadFrom(conn)

the net package doesn't provide anything good to fight the leaky
abstractions. you need to have a look at
http://golang.org/pkg/bytes/#Buffer.ReadFrom.

ps: read operation on udp socket is basically per-datagram basis, no EOF.

boghi...@gmail.com

unread,
Sep 12, 2014, 11:38:17 AM9/12/14
to golan...@googlegroups.com, boghi...@gmail.com
So how do I read the whole data from the socket without creating a 64k slice? Is there some delimiter character I can use?

James Bardin

unread,
Sep 12, 2014, 11:48:45 AM9/12/14
to golan...@googlegroups.com, boghi...@gmail.com


On Friday, September 12, 2014 11:38:17 AM UTC-4, boghi...@gmail.com wrote:
So how do I read the whole data from the socket without creating a 64k slice? Is there some delimiter character I can use?


You basically have to use a buffer that can handle the maximum packet size you might see. If you don't have an upper bound, having a single 64k buffer isn't really a big deal unless you're on some embedded system. There is a rather awkward mechanisms to get the incoming packet size, but I don't think there's any feasible way to do it in Go.

boghi...@gmail.com

unread,
Sep 12, 2014, 1:45:56 PM9/12/14
to golan...@googlegroups.com, boghi...@gmail.com
I still don't get why my code doesn't work. What have I done wrong? I have tried it with a []byte, net.ResolveUDPAddr. So far nothing is working.

James Bardin

unread,
Sep 12, 2014, 2:07:48 PM9/12/14
to golan...@googlegroups.com, boghi...@gmail.com


On Thursday, September 11, 2014 12:44:49 PM UTC-4, boghi...@gmail.com wrote:
So, I need to write an UDP Server/Client in Go. So far it's either been nothing or 100% CPU hogging resulting in death. Here's part of my client code:
addr := net.UDPAddr{
        Port: 2000,
        IP: net.ParseIP("127.0.0.1"),
    }
conn, _ := net.DialUDP("udp", nil, &addr)
var buff bytes.Buffer
buff.ReadFrom(conn)

As Mikio said, UDP doesn't have an EOF, so you can't use ReadFrom. Just read into a []byte slice like usual.

 
fmt.Println(string(buff.Bytes()))

and the server:
addr := net.UDPAddr{
        Port: 2000,
        IP: net.ParseIP("127.0.0.1"),
    }
    conn, err := net.ListenUDP("udp", &addr) 
    defer conn.Close()
    if err != nil {
        panic(err)
    }
    var buf [1024]byte
    for {
    conn.ReadFromUDP(buf[:])

You're also not checking the read length, or errors, anywhere. You *need* the bytes in order know where to slice buf.

 
    conn.Write([]byte("OK"))

This is a listening connection. You can't send because there's no destination address (you would see this if you checked the error)
 
conn.Close()

You're closing the connection in your for loop, causing it to go into an infinite loop. Check errors again.
 

boghi...@gmail.com

unread,
Sep 12, 2014, 2:13:58 PM9/12/14
to golan...@googlegroups.com, boghi...@gmail.com
I've rewritten the code, so everything is nice, except the write part. Also, do I need the ReadFromUDP before the loop, or inside it?

James Bardin

unread,
Sep 12, 2014, 3:19:33 PM9/12/14
to golan...@googlegroups.com, boghi...@gmail.com


On Friday, September 12, 2014 2:13:58 PM UTC-4, boghi...@gmail.com wrote:
I've rewritten the code, so everything is nice, except the write part.

I don't understand, do you have a question about Write()?
 
Also, do I need the ReadFromUDP before the loop, or inside it?


If you're using a loop, I assume you want to read more than one datagram?
If you only want to read once, then you don't need a loop.



boghi...@gmail.com

unread,
Sep 13, 2014, 10:30:04 AM9/13/14
to golan...@googlegroups.com, boghi...@gmail.com
I've updated the code, so server:
package main

import (
"net"
    "fmt"
)

func main() {
    addr, _ := net.ResolveUDPAddr("udp", ":2000")
    conn, err := net.ListenUDP("udp", addr)
    defer conn.Close()
    if err != nil {
        panic(err)
    }
    var buf [512]byte
    for {
    _, nextAddr, _ := conn.ReadFromUDP(buf[0:])
    fmt.Println("yay")
    conn.WriteToUDP([]byte("OK"), nextAddr)
}
}

client:

addr, _ := net.ResolveUDPAddr("udp", ":2000")
conn, _ := net.DialUDP("udp", nil, addr)
var buff [512]byte
n, _, _ := conn.ReadFromUDP(buff[0:])
fmt.Println(string(buff[0:n]))

still nothing works :(

Tamás Gulácsi

unread,
Sep 13, 2014, 1:46:58 PM9/13/14
to golan...@googlegroups.com
You still not Chow ng the returned errors.

James Bardin

unread,
Sep 13, 2014, 5:24:53 PM9/13/14
to boghi...@gmail.com, golan...@googlegroups.com
Stop ignoring errors. They will likely tell you exactly what is wrong. 
--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/oYlZaUnWdIU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mikio Hara

unread,
Sep 13, 2014, 9:31:55 PM9/13/14
to Bogdan Cuza, golang-nuts
On Sat, Sep 13, 2014 at 11:30 PM, <boghi...@gmail.com> wrote:

> still nothing works :(

looks like your confusion is not related to the go standard library,
it comes from the underlying stuff: network protools and kernel
services that try to abstract the way of access to each protocol.
fwiw, the net package holds tons of dumb test cases and perhaps it
might be help you.

PacketConn peers: http://golang.org/src/pkg/net/packetconn_test.go#L67
Conn server and PacketConn client:
http://golang.org/src/pkg/net/packetconn_test.go#L122

Dave Cheney

unread,
Sep 13, 2014, 11:02:59 PM9/13/14
to golan...@googlegroups.com, boghi...@gmail.com


On Sunday, 14 September 2014 00:30:04 UTC+10, boghi...@gmail.com wrote:
I've updated the code, so server:
package main

import (
"net"
    "fmt"
)

func main() {
    addr, _ := net.ResolveUDPAddr("udp", ":2000")
    conn, err := net.ListenUDP("udp", addr)
    defer conn.Close()
    if err != nil {
        panic(err)
    }
    var buf [512]byte
    for {
    _, nextAddr, _ := conn.ReadFromUDP(buf[0:])

You've ignored the size of the number of bytes read into buf (it may not be 512), and also the error.
 
    fmt.Println("yay")
    conn.WriteToUDP([]byte("OK"), nextAddr)
}
}

client:

addr, _ := net.ResolveUDPAddr("udp", ":2000")
conn, _ := net.DialUDP("udp", nil, addr)
var buff [512]byte
n, _, _ := conn.ReadFromUDP(buff[0:])
fmt.Println(string(buff[0:n]))

still nothing works :(

You need to check all the errors before we can offer you more constructive feedback.

boghi...@gmail.com

unread,
Sep 14, 2014, 2:44:13 AM9/14/14
to golan...@googlegroups.com, boghi...@gmail.com
I checked the errors and guess what: no errors whatsoever. I've considered packet loss, but since it's localhost to localhost, i doubt it. The buffer is more that enough: the server doesn't even need to read anything and the client reads OK, how many bytes do you think are in OK?

Jesse McNelis

unread,
Sep 14, 2014, 2:51:47 AM9/14/14
to boghi...@gmail.com, golang-nuts
On Sun, Sep 14, 2014 at 12:30 AM, <boghi...@gmail.com> wrote:
> I've updated the code, so server:
> package main
>
> import (
> "net"
> "fmt"
> )
>
> func main() {
> addr, _ := net.ResolveUDPAddr("udp", ":2000")
> conn, err := net.ListenUDP("udp", addr)
> defer conn.Close()
> if err != nil {
> panic(err)
> }
> var buf [512]byte
> for {
> _, nextAddr, _ := conn.ReadFromUDP(buf[0:])
> fmt.Println("yay")
> conn.WriteToUDP([]byte("OK"), nextAddr)
> }
> }

Your server is waiting to receive data from the client.

> client:
>
> addr, _ := net.ResolveUDPAddr("udp", ":2000")
> conn, _ := net.DialUDP("udp", nil, addr)
> var buff [512]byte
> n, _, _ := conn.ReadFromUDP(buff[0:])
> fmt.Println(string(buff[0:n]))

Your client is waiting to receive data from the server.


> still nothing works :(

You have a deadlock.

boghi...@gmail.com

unread,
Sep 14, 2014, 3:32:58 AM9/14/14
to golan...@googlegroups.com, boghi...@gmail.com, jes...@jessta.id.au
So, I added WriteToUDP into the client code and it still doesn't work.

boghi...@gmail.com

unread,
Sep 14, 2014, 5:02:42 AM9/14/14
to golan...@googlegroups.com, boghi...@gmail.com
OK, I've fixed the client and everything works finally. I replaced DialUDP with Dial, WriteToUDP with Write and ReadFromUDP to Read. Can anybody tell me how I can read the data till the end from read instead of having a buffer?

Dave Cheney

unread,
Sep 14, 2014, 5:05:48 AM9/14/14
to boghi...@gmail.com, golan...@googlegroups.com
UDP doesn't have a concept of end, packets must be read in full on the first try, packets may also arrive out of order or not at all. If you use UDP you need to deal with these eventualities. 



On 14 Sep 2014, at 19:02, boghi...@gmail.com wrote:

OK, I've fixed the client and everything works finally. I replaced DialUDP with Dial, WriteToUDP with Write and ReadFromUDP to Read. Can anybody tell me how I can read the data till the end from read instead of having a buffer?

--
Reply all
Reply to author
Forward
0 new messages