Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@s-shin
Created June 7, 2017 14:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save s-shin/5a2b497d3facce35003148befbcae375 to your computer and use it in GitHub Desktop.
Save s-shin/5a2b497d3facce35003148befbcae375 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"bytes"
"encoding/binary"
"fmt"
"io"
"log"
"net"
)
func splitChunk(data []byte, atEOF bool) (int, []byte, error) {
if len(data) == 0 && atEOF {
return 0, nil, io.EOF
}
buf := bytes.NewReader(data)
var dataSize uint32
err := binary.Read(buf, binary.LittleEndian, &dataSize)
if err != nil {
if atEOF {
return 0, nil, fmt.Errorf("too short data")
}
return 0, nil, nil // read more
}
dataSizeWithSizeHeader := dataSize + 4
if uint32(len(data)) < dataSizeWithSizeHeader {
if atEOF {
return 0, nil, fmt.Errorf("too short data")
}
return 0, nil, nil // read more
}
return int(dataSizeWithSizeHeader), data[4:dataSizeWithSizeHeader], nil
}
type ClientID int
var lastClientID ClientID
type Client struct {
ID ClientID
conn net.Conn
}
func NewClient(conn net.Conn) *Client {
lastClientID++
return &Client{ID: lastClientID, conn: conn}
}
func (c *Client) Activate() {
defer c.conn.Close()
scanner := bufio.NewScanner(c.conn)
scanner.Split(splitChunk)
for scanner.Scan() {
log.Printf("client[%d]: %s", c.ID, scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Printf("client[%d]: %s", c.ID, err)
} else {
log.Printf("client[%d]: disconnected", c.ID)
}
}
type App struct {
clients map[ClientID]*Client
}
func NewApp() *App {
return &App{
clients: make(map[ClientID]*Client),
}
}
func (a *App) HandleConnection(conn net.Conn) {
log.Printf("app: new conection")
c := NewClient(conn)
a.clients[c.ID] = c
c.Activate()
}
func main() {
app := NewApp()
log.Printf("listen to :5000")
l, err := net.Listen("tcp", ":5000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
go app.HandleConnection(conn)
}
}
#!/bin/bash
set -eux
# OK
printf "\x0D\x00\x00\x00%s" 'Hello, world!' | nc localhost 5000
# too short data
printf "\x0D\x00\x00\x00%s" 'Hello, world! ' | nc localhost 5000
# OK
printf "\x0D\x00\x00\x00%s\x03\x00\x00\x00%s" 'Hello, world!' 'Hi!' | nc localhost 5000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment