Skip to content

Latest commit

 

History

History
138 lines (109 loc) · 2.73 KB

the_codec_type.md

File metadata and controls

138 lines (109 loc) · 2.73 KB

The Codec type

The Message and JSON objects are both instances of the type Codec. This type is defined by

type Codec struct {
    Marshal   func(v interface{}) (data []byte, payloadType byte, err error)
    Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
}

The type Codec implements the Send and Receive methods used earlier.

It is likely that websockets will also be used to exchange XML data. We can build an XML Codec object by wrapping the XML marshal and unmarshal methods discussed in Chapter 12: XML to give a suitable Codec object.

We can create a XMLCodec package in this way:

package xmlcodec

import (
	"encoding/xml"
	"code.google.com/p/go.net/websocket"
)

func xmlMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
	//buff := &bytes.Buffer{}
	msg, err = xml.Marshal(v)
	//msgRet := buff.Bytes()
	return msg, websocket.TextFrame, nil
}

func xmlUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
	// r := bytes.NewBuffer(msg)
	err = xml.Unmarshal(msg, v)
	return err
}

var XMLCodec = websocket.Codec{xmlMarshal, xmlUnmarshal}

We can then serialise Go objects such as a Person into an XML document and send it from a client to a server by

/* PersonClientXML
 */
package main

import (
	"code.google.com/p/go.net/websocket"
	"fmt"
	"os"
	"xmlcodec"
)

type Person struct {
	Name   string
	Emails []string
}

func main() {
	if len(os.Args) != 2 {
		fmt.Println("Usage: ", os.Args[0], "ws://host:port")
		os.Exit(1)
	}
	service := os.Args[1]

	conn, err := websocket.Dial(service, "", "http://localhost")
	checkError(err)

	person := Person{Name: "Jan",
		Emails: []string{"[email protected]", "[email protected]"},
	}

	err = xmlcodec.XMLCodec.Send(conn, person)
	if err != nil {
		fmt.Println("Couldn't send msg " + err.Error())
	}
	os.Exit(0)
}

func checkError(err error) {
	if err != nil {
		fmt.Println("Fatal error ", err.Error())
		os.Exit(1)
	}
}

A server which receives this and just prints information to the console is

/* PersonServerXML
 */
package main

import (
	"code.google.com/p/go.net/websocket"
	"fmt"
	"net/http"
	"os"
	"xmlcodec"
)

type Person struct {
	Name   string
	Emails []string
}

func ReceivePerson(ws *websocket.Conn) {
	var person Person
	err := xmlcodec.XMLCodec.Receive(ws, &person)
	if err != nil {
		fmt.Println("Can't receive")
	} else {

		fmt.Println("Name: " + person.Name)
		for _, e := range person.Emails {
			fmt.Println("An email: " + e)
		}
	}
}

func main() {

	http.Handle("/", websocket.Handler(ReceivePerson))
	err := http.ListenAndServe(":12345", nil)
	checkError(err)
}

func checkError(err error) {
	if err != nil {
		fmt.Println("Fatal error ", err.Error())
		os.Exit(1)
	}
}