-
-
Save hyper0x/8f724925c344f896b63c to your computer and use it in GitHub Desktop.
package main | |
import ( | |
"bufio" | |
"bytes" | |
"fmt" | |
"io" | |
"log" | |
"net" | |
"os" | |
"sync" | |
"time" | |
) | |
const ( | |
DELIMITER byte = '\n' | |
QUIT_SIGN = "quit!" | |
) | |
func Read(conn net.Conn, delim byte) (string, error) { | |
reader := bufio.NewReader(conn) | |
var buffer bytes.Buffer | |
for { | |
ba, isPrefix, err := reader.ReadLine() | |
if err != nil { | |
if err == io.EOF { | |
break | |
} | |
return "", err | |
} | |
buffer.Write(ba) | |
if !isPrefix { | |
break | |
} | |
} | |
return buffer.String(), nil | |
} | |
func Write(conn net.Conn, content string) (int, error) { | |
writer := bufio.NewWriter(conn) | |
number, err := writer.WriteString(content) | |
if err == nil { | |
err = writer.Flush() | |
} | |
return number, err | |
} | |
func main() { | |
go func() { | |
listener, err := net.Listen("tcp", ":9090") | |
if err != nil { | |
log.Printf("Listener: Listen Error: %s\n", err) | |
os.Exit(1) | |
} | |
log.Println("Listener: Listening...") | |
for { | |
conn, err := listener.Accept() | |
if err != nil { | |
log.Printf("Listener: Accept Error: %s\n", err) | |
continue | |
} | |
go func(conn net.Conn) { | |
defer conn.Close() | |
for { | |
log.Println("Listener: Accepted a request.") | |
log.Println("Listener: Read the request content...") | |
content, err := Read(conn, DELIMITER) | |
if err != nil { | |
log.Printf("Listener: Read error: %s", err) | |
} | |
if content == QUIT_SIGN { | |
log.Println("Listener: Quit!") | |
break | |
} | |
log.Printf("Listener: Received content: %s\n", content) | |
respContent := fmt.Sprintf("listener response: %s%c", content, DELIMITER) | |
log.Printf("Listener: the response content: %s\n", respContent) | |
num, err := Write(conn, respContent) | |
if err != nil { | |
log.Printf("Listener: Write Error: %s\n", err) | |
} | |
log.Printf("Listener: Wrote %d byte(s)\n", num) | |
} | |
}(conn) | |
} | |
}() | |
time.Sleep(time.Millisecond * 500) | |
var wg sync.WaitGroup | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
conn, err := net.DialTimeout("tcp", "127.0.0.1:9090", time.Millisecond*200) | |
if err != nil { | |
log.Printf("Sender: DialTimeout Error: %s\n", err) | |
os.Exit(1) | |
} | |
log.Println("Sender: Dial OK.") | |
for i := 0; i < 10; i++ { | |
reqContent := fmt.Sprintf("sender request %d.%c", i, DELIMITER) | |
log.Printf("Sender: the request content: %s\n", reqContent) | |
num, err := Write(conn, reqContent) | |
if err != nil { | |
log.Printf("Sender: Write Error: %s\n", err) | |
break | |
} | |
log.Printf("Sender: Wrote %d byte(s)\n", num) | |
respContent, err := Read(conn, DELIMITER) | |
if err != nil { | |
log.Printf("Sender: Read error: %s", err) | |
break | |
} | |
log.Printf("Sender: Received content: %s\n", respContent) | |
} | |
reqContent := fmt.Sprintf("%s%c", QUIT_SIGN, DELIMITER) | |
log.Printf("Sender: the request content: %s\n", reqContent) | |
num, err := Write(conn, reqContent) | |
if err != nil { | |
log.Printf("Sender: Write Error: %s\n", err) | |
} | |
log.Printf("Sender: Wrote %d byte(s)\n", num) | |
}() | |
wg.Wait() | |
time.Sleep(time.Millisecond * 500) | |
} |
This allows data in multiple connections to not interfere with each other. You can also use only one reader/writer per connection, but be aware that you must reset them when appropriate.
i've used your example, i don't understard why it look read function lose some lines
i've used your example, i don't understard why it look read function lose some lines
Can you tell me the details? You can provide screenshots or other things.
I would extract some of the inline functions to reduce the nesting and increase the readability.
I would extract some of the inline functions to reduce the nesting and increase the readability.
OK, it's valuable.
Could be a good option use scanner := bufio.NewScanner(conn)
in place of bufio.NewReader(conn)
then is possible use scanner.Split(bufio.ScanWords)
?
A great example, thank you!
I am wondering why we need to create a new
bufio.Writer
/bufio.Reader
for each write/read in a single connection.