Golang send and receive udp packets simultaneously - go

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,)

Related

"Infinitely" high data transfer with Golang TCP connection on localhost

Problem
I have written a TCP echo server in Go and I am trying to write/read as often as I can in 10s to measure how much data got transfered in this time. Weirdly, the value is way too high and does not depend on the length of the bytearray which I am transfering (but it should!). It is always around 600k connections in this 10 seconds (The length of the "result" Array depicts how much connections were made in the 10s). As soon as I add let's say a print statement to the server and the values get processed, I get more realistic values that depend on the length of the bytearray as a result.
Why doesn't the length of the bytearray matter in the first case?
Code
Server
package main
import (
"fmt"
"log"
"net"
)
func main() {
tcpAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:8888"))
checkError(err)
ln, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
for {
conn, err := ln.Accept()
checkError(err)
go handleConnection(conn)
}
}
func checkError(err error) {
if err != nil {
log.Fatal(err)
}
}
func handleConnection(conn net.Conn) {
var input [1000000]byte
for {
n, err := conn.Read(input[0:])
checkError(err)
//fmt.Println(input[0:n])
_, err = conn.Write(input[0:n])
checkError(err)
}
}
Client
package main
import (
"fmt"
"log"
"net"
"time"
)
var (
result []int
elapsed time.Duration
)
func main() {
input := make([]byte, 1000)
tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8888")
checkError(err)
conn, err := net.DialTCP("tcp", nil, tcpAddr)
checkError(err)
for start := time.Now(); time.Since(start) < time.Second*time.Duration(10); {
startTimer := time.Now()
_, err = conn.Write(input)
checkError(err)
_, err := conn.Read(input[0:])
checkError(err)
elapsed = time.Since(startTimer)
result = append(result, int(elapsed))
}
fmt.Println(fmt.Sprintf("result: %v", len(result)))
}
func checkError(err error) {
if err != nil {
log.Fatal(err)
}
}
Read in the client loop is not guaranteed to read all of the data sent in the previous call to Write.
When input is small enough to be transmitted in a single packet on the network, Read in the client returns all of the data in the previous call to Write in the client. In this mode, the application measures the time to execute request/response pairs.
For larger sizes of input, read on the client can fall behind what the client is writing. When this happens, the calls to Read complete faster because the calls return data from an earlier call to Write. The application is pipelining in this mode. The throughput for pipelining is higher than the throughput for request/response pairs. The client will not read all data in this mode, but the timing impact of that is not significant.
Use the following code to time request/response pairs for arbitrary sizes of input.
for start := time.Now(); time.Since(start) < time.Second*time.Duration(10); {
startTimer := time.Now()
_, err = conn.Write(input)
checkError(err)
_, err := io.ReadFull(conn, input) // <-- read all of the data
checkError(err)
elapsed = time.Since(startTimer)
result = append(result, int(elapsed))
}
To measure full-on pipelining, modify the client to read and write from different goroutines. An example follows.
go func() {
for start := time.Now(); time.Since(start) < time.Second*time.Duration(10); {
_, err = conn.Write(input)
checkError(err)
}
conn.CloseWrite() // tell server that we are done sending data
}()
start := time.Now()
output := make([]byte, 4096)
for {
_, err := conn.Read(output)
if err != nil {
if err == io.EOF {
break
}
checkError(err)
}
}
fmt.Println(time.Since(start))

golang not writing to file in server app

I'm writing a simple tcp server in golang that writes to "output.txt". All the "server part" works fine, but it does not write to file.(but it does create "output.txt")
func handleRequest(conn net.Conn) {
// Make a buffer to hold incoming data.
buf := make([]byte, 1024)
// Read the incoming connection into the buffer.
size, err := conn.Read(buf)
if err != nil {
fmt.Println("Error reading:", err.Error())
}
s := string(buf[:size])
fmt.Println(s)
perm := os.FileMode(0644)
err = ioutil.WriteFile("output.txt", buf, perm)
check(err)
// Close the connection when you're done with it.
conn.Close()
}
Why does it not write to file and how to fix this?

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)

ListenUDP, a one way street?

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)
}

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