From f44c19868cf1c4d453bfe838c600f63e2ac073b0 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 11 Mar 2020 23:54:35 +0800 Subject: [PATCH] improve package gudp --- net/gudp/gudp_conn.go | 67 +++++++------------------------- net/gudp/gudp_func.go | 11 ------ net/gudp/gudp_unit_basic_test.go | 35 ++++++++++++++++- 3 files changed, 48 insertions(+), 65 deletions(-) diff --git a/net/gudp/gudp_conn.go b/net/gudp/gudp_conn.go index c9f1a9f3f..059775413 100644 --- a/net/gudp/gudp_conn.go +++ b/net/gudp/gudp_conn.go @@ -23,7 +23,7 @@ type Conn struct { const ( gDEFAULT_RETRY_INTERVAL = 100 * time.Millisecond // Retry interval. - gDEFAULT_READ_BUFFER_SIZE = 64 // (Byte)Buffer size. + gDEFAULT_READ_BUFFER_SIZE = 1024 // (Byte)Buffer size. gRECV_ALL_WAIT_TIMEOUT = time.Millisecond // Default interval for reading buffer. ) @@ -83,68 +83,32 @@ func (c *Conn) Send(data []byte, retry ...Retry) (err error) { } // Recv receives data from remote address. +// The parameter is used for customizing the receiving buffer size. The default +// buffer size is 1024 byte. // -// Note that, -// 1. There's package border in UDP protocol, so we can receive a complete package if it specifies length < 0. -// 2. If length = 0, it means it receives the data from current buffer and returns immediately. -// 3. If length > 0, it means it blocks reading data from connection until length size was received. -func (c *Conn) Recv(length int, retry ...Retry) ([]byte, error) { +// There's package border in UDP protocol, we can receive a complete package if specified +// buffer size is big enough. VERY NOTE that we should receive the complete package in once +// or else the leftover package data would be dropped. +func (c *Conn) Recv(buffer int, retry ...Retry) ([]byte, error) { var err error // Reading error. var size int // Reading size. - var index int // Received size. - var buffer []byte // Buffer object. - var bufferWait bool // Whether buffer reading timeout set. + var data []byte // Buffer object. var remoteAddr *net.UDPAddr // Current remote address for reading. - - if length > 0 { - buffer = make([]byte, length) + if buffer > 0 { + data = make([]byte, buffer) } else { - buffer = make([]byte, gDEFAULT_READ_BUFFER_SIZE) + data = make([]byte, gDEFAULT_READ_BUFFER_SIZE) } - for { - if length < 0 && index > 0 { - bufferWait = true - if err = c.SetReadDeadline(time.Now().Add(c.recvBufferWait)); err != nil { - return nil, err - } - } - size, remoteAddr, err = c.ReadFromUDP(buffer[index:]) + size, remoteAddr, err = c.ReadFromUDP(data) if err == nil { c.remoteAddr = remoteAddr } - if size > 0 { - index += size - if length > 0 { - // It reads til size if is specified. - if index == length { - break - } - } else { - if index >= gDEFAULT_READ_BUFFER_SIZE { - // If it exceeds the buffer size, it then automatically increases its buffer size. - buffer = append(buffer, make([]byte, gDEFAULT_READ_BUFFER_SIZE)...) - } else { - // It returns immediately if received size is lesser than buffer size. - if !bufferWait { - break - } - } - } - } if err != nil { // Connection closed. if err == io.EOF { break } - // Re-set the timeout when reading data. - if bufferWait && isTimeout(err) { - if err = c.SetReadDeadline(c.recvDeadline); err != nil { - return nil, err - } - err = nil - break - } if len(retry) > 0 { // It fails even it retried. if retry[0].Count == 0 { @@ -159,12 +123,9 @@ func (c *Conn) Recv(length int, retry ...Retry) ([]byte, error) { } break } - // Just read once from buffer. - if length == 0 { - break - } + break } - return buffer[:index], err + return data[:size], err } // SendRecv writes data to connection and blocks reading response. diff --git a/net/gudp/gudp_func.go b/net/gudp/gudp_func.go index 0e8042c8c..a4d08fe6d 100644 --- a/net/gudp/gudp_func.go +++ b/net/gudp/gudp_func.go @@ -52,14 +52,3 @@ func SendRecv(address string, data []byte, receive int, retry ...Retry) ([]byte, defer conn.Close() return conn.SendRecv(data, receive, retry...) } - -// isTimeout checks whether given is a timeout error. -func isTimeout(err error) bool { - if err == nil { - return false - } - if netErr, ok := err.(net.Error); ok && netErr.Timeout() { - return true - } - return false -} diff --git a/net/gudp/gudp_unit_basic_test.go b/net/gudp/gudp_unit_basic_test.go index 4b8448de1..956d36702 100644 --- a/net/gudp/gudp_unit_basic_test.go +++ b/net/gudp/gudp_unit_basic_test.go @@ -28,7 +28,7 @@ func Test_Basic(t *testing.T) { } } if err != nil { - glog.Error(err) + break } } }) @@ -71,3 +71,36 @@ func Test_Basic(t *testing.T) { } }) } + +// If the read buffer size is less than the sent package size, +// the rest data would be dropped. +func Test_Buffer(t *testing.T) { + p := ports.PopRand() + s := gudp.NewServer(fmt.Sprintf("127.0.0.1:%d", p), func(conn *gudp.Conn) { + defer conn.Close() + for { + data, err := conn.Recv(1) + if len(data) > 0 { + if err := conn.Send(data); err != nil { + glog.Error(err) + } + } + if err != nil { + break + } + } + }) + go s.Run() + defer s.Close() + time.Sleep(100 * time.Millisecond) + gtest.Case(t, func() { + result, err := gudp.SendRecv(fmt.Sprintf("127.0.0.1:%d", p), []byte("123"), -1) + gtest.Assert(err, nil) + gtest.Assert(string(result), "1") + }) + gtest.Case(t, func() { + result, err := gudp.SendRecv(fmt.Sprintf("127.0.0.1:%d", p), []byte("456"), -1) + gtest.Assert(err, nil) + gtest.Assert(string(result), "4") + }) +}