NetWork & IOI/O and binary programming
2013/11/14#GoCon
Jack
● id: Jxck● github: Jxck● twitter: jxck_● about: http://jxck.io● blog: http://d.hatena.ne.jp/jxck● Love: music
Now working on ...
● http2 server/client○ github.com/Jxck/http2○ github.com/Jxck/hpack○ github.com/Jxck/logger○ github.com/Jxck/color
● Caution○ not enough error handling○ not enough test○ not enough api/feature○ under heavy working :p
network serverI/O and binary programming
NetWork Server in Go
● net● []byte● bytes● encoding/binary● io● io/ioutil● bufio
No Error Handling in Sample Codesfunc main() {
listener, err := net.Listen("tcp", "127.0.0.1:3000") // err
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept() // err
if err != nil {
log.Fatal(err)
}
defer func() {
log.Println("close connection")
conn.Close()
}()
_, err = conn.Write([]byte("hello\n")) // send hello
if err != nil {
log.Fatal(err)
}
}
}Hard To Read on Slide
import “net”tcp server in go
TCP Serverpackage main
import "net"
func main() {
listener, _ := net.Listen("tcp", ":3000")
for {
conn, _ := listener.Accept()
conn.Write([]byte("hello\n"))
conn.Close()
}
}
TCP Server With Handlerfunc main() {
listener, _ := net.Listen("tcp", ":3000")
for {
conn, _ := listener.Accept()
handleConn(conn)
}
}
func handleConn(conn net.Conn) {
conn.Write([]byte("hello\n"))
}
TCP Server with Goroutinefunc main() {
listener, _ := net.Listen("tcp", ":3000")
for {
conn, _ := listener.Accept()
go handleConn(conn)
}
}
func handleConn(conn net.Conn) {
conn.Write([]byte("hello\n"))
}
[]bytehandle octet stream in go
binary format (example)
R Length(14) Type(8) Flags(8)
R Stream Identifier(31)
Reserved(8) Setting Identifier(24)
Value(32)
[]byte{0, 8, 4, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 16, 0}
low level byte slice handlingfunc main() {
b := []byte{}
b = append(b, []byte{0, 8}...) // length 8
b = append(b, 4) // type 4
b = append(b, 0) // flags 0
// stream id 1
b = append(b, []byte{0, 0, 0, 1}...)
// settings id 1
b = append(b, []byte{0, 0, 0, 1}...)
// value 4096
b = append(b, []byte{0, 0, 16, 0}...)
fmt.Println(b)
// [0 8 4 0 0 0 0 1 0 0 0 1 0 0 16 0]
}
SWrap (slice wrap)import “github.com/Jxck/swrap”
type SWrap● func New(a []byte) SWrap
● func (sw *SWrap) Add(a byte)
● func (sw *SWrap) Bytes() []byte
● func (sw *SWrap) Compare(b []byte) bool
● func (sw *SWrap) Delete(i int)
● func (sw *SWrap) Len() int
● func (sw *SWrap) Merge(a []byte)
● func (sw *SWrap) Pop() byte
● func (sw *SWrap) Push(b byte)
● func (sw *SWrap) Replace(i int, b byte)
● func (sw *SWrap) Shift(b byte)
● func (sw *SWrap) UnShift() byte
import “io”handle IO in go
important: io.Reader, io.Writertype Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type ReadWriter interface {
Reader
Writer
}
net.Conn implements io.Writerfunc handleConn(conn net.Conn) {
conn.Write([]byte("hello\n"))
}
func handleConn(conn io.Writer) {
conn.Write(
[]byte{104, 101, 108, 108, 111, 10}
)
}
import “bytes”utility for byte slice and Buffer
bytes.Buffer: io.ReadWriter for []bytefunc handleConn(conn io.Writer) {
conn.Write([]byte{104, 101, 108, 108, 111, 10})
}
func main() {
b := []byte{}
buf := bytes.NewBuffer(b) // io.ReadeWriter
handleConn(buf)
actual := buf.Bytes()
bytes.Equal(
actual,
[]byte{104, 101, 108, 108, 111, 10},
) // true
}
import “encoding/binary”
read/write fixed size value
we did...func main() {
b := []byte{}
b = append(b, []byte{0, 8}...) // length 8
b = append(b, 4) // type 4
b = append(b, 0) // flags 0
// stream id 1
b = append(b, []byte{0, 0, 0, 1}...)
// settings id 1
b = append(b, []byte{0, 0, 0, 1}...)
// value 4096
b = append(b, []byte{0, 0, 16, 0}...)
fmt.Println(b)
// [0 8 4 0 0 0 0 1 0 0 0 1 0 0 16 0]
}
Fixed Size
R Length(14) Type(8) Flags(8)
R Stream Identifier(31)
Reserved(8) Setting Identifier(24)
Value(32)
var Length uint16 = 8
var Type, Flags uint8 = 4, 0
var StreamId, SettingsId uint32 = 1, 1
var Value uint32 = 4096
encoding/binary.Write()buf := bytes.NewBuffer([]byte{})
var Length uint16 = 8
var Type, Flags uint8 = 4, 0
var StreamId, SettingsId uint32 = 1, 1
var Value uint32 = 4096
binary.Write(buf, binary.BigEndian, Length)
binary.Write(buf, binary.BigEndian, Type)
// ...
binary.Write(buf, binary.BigEndian, Value)
fmt.Println(buf.Bytes())
// [0 8 4 0 0 0 0 1 0 0 0 1 0 0 16 0]
encoding/binary.Write()buf := bytes.NewBuffer([]byte{})
frame := Frame{
Length: 8,
Type: 4,
Flags: 0,
StreamId: 1,
SettingsId: 1,
Value: 4096,
}
// func Write(w io.Writer, order ByteOrder, data
interface{}) error
binary.Write(buf, binary.BigEndian, frame)
fmt.Println(buf.Bytes())
type Frame struct {
Length uint16
Type uint8
Flags uint8
StreamId uint32
SettingsId uint32
Value uint32
}
import “net”tcp client in go
TCP Clientfunc main() {
conn, _ := net.Dial("tcp", ":3000")
b := make([]byte, 100)
n, _ := conn.Read(b)
fmt.Print(string(b[:n]))
// hello
}
import “bufio”buffered io
bufio := []byte(4096) + io// bufio.Reader
type Reader struct {}
// bufio.Writer
type Writer struct {}
func NewReader(rd io.Reader) *Reader {
// convert io.Reader to *bufio.Reader
}
func NewWriter(wr io.Writer) *Writer {
// convert io.Writer to *bufio.Writer
}
TCP Client with bufiofunc main() {
conn, _ := net.Dial("tcp", ":3000")
br := bufio.NewReader(conn)
line, _ := br.ReadString('\n')
fmt.Print(line) // hello
}
TCP Client with encoding/binarytype Frame struct {
Length uint16
Type uint8
Flags uint8
StreamId uint32
SettingsId uint32
Value uint32
}
func main() {
conn, _ := net.Dial("tcp", ":3000")
frame := &Frame{}
binary.Read(conn, binary.BigEndian, frame)
fmt.Print(frame) // &{8 4 0 1 1 4096}
}
HTTP/2.0?
HTTP/2.0 with Go
● tcp/tls connection○ net
● multiplexed stream○ goroutine / channel
● binary frame○ static type / encoding/binary
● crypto○ crypto
● build○ go build (cross compile)
● test○ go test (and testing)
HTTP2.0 Study (#http2study)
● http2.0 勉強会 #2○ http://bit.ly/158zE4C
● http2.0 hackathon○ 12月 or 1月
anyone ?
Q & A
thanks :)
END
Top Related