Go語言網路編程樣本-用戶端篇

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

// occlient project main.gopackage mainimport ("crypto/md5""encoding/hex""flag""log""os""runtime""time")func MD5(b []byte) string {h := md5.New()h.Write(b)x := h.Sum(nil)y := make([]byte, 32)hex.Encode(y, x)return string(y)}var sleep time.Durationfunc DateTime_YYYYMMDDHHMMSS() string {return time.Now().Format("20060102150405")}func main() {runtime.GOMAXPROCS(1000000)addr := flag.String("addr", "127.0.0.1:5555", "message server address and port ,default 180.153.149.147:8443")user := flag.Int("uid", 10000, "user login id,default 10000")sec := flag.String("sec", "abc", "secrity key")room := flag.Int("rid", 11111, "client type,default 11111")c := flag.Int("c", 1, "concurrent number,default 1")t := flag.Int("t", 1, "precent %t% second send a message ,default 1 s")sleep = time.Duration(*t) * time.Secondflag.Parse()for i := 1; i <= *c; i++ {go doconnect(*addr, int32(*user)+int32(i), int32(*room), *sec)}select {}os.Exit(0)}func doconnect(addr string, uid int32, room int32, key string) {client := NewClient(addr, uid, room, key)for {ok := client.Handshake()if ok {ok = client.Join()break}client.Logout()log.Printf("Reconnect %+v", client)}//partten := "20060102150405"for {if client.IsLogin() {client.SendMessage("Hello Openchat")time.Sleep(sleep)} else {client.Logout()doconnect(addr, uid, room, key)}}//defer client.Logout()//defer client.Logout()}func checkError(msg string, err error) {if err != nil {log.Println(msg, err)}}// occlientpackage mainimport ("bytes""encoding/binary""io""log""net""time")type Client struct {Address  stringUserId   int32RoomId   int32SecKey   stringsequence int32logined  boolsession  net.ConnnextInt  func() int32}func NewClient(addr string, user int32, room int32, key string) *Client {c := new(Client)c.sequence = 0c.Address = addrc.UserId = userc.RoomId = roomc.SecKey = keyc.logined = falsec.nextInt = intSeq()return c}func intSeq() func() int32 {var i int32 = 0return func() int32 {i += 1return i}}func (c *Client) IsLogin() bool {return c.logined}func (c *Client) Logout() {c.logined = falseif c.session != nil {c.session.Close()}}func readPacket(conn net.Conn) ([]byte, error) {result := bytes.NewBuffer(nil)tb := make([]byte, 4)conn.SetReadDeadline(time.Now().Add(time.Second * 30))i, err := io.ReadFull(conn, tb)result.Write(tb[0:i])if err != nil {return result.Bytes(), err}var length int32err = binary.Read(result, binary.BigEndian, &length)if length > 4096 {conn.Close()log.Printf("Invalid Length %d", length)return result.Bytes(), err}result = bytes.NewBuffer(nil)result.Write(tb)tb = make([]byte, length)conn.SetReadDeadline(time.Now().Add(time.Second * 30))i, err = io.ReadFull(conn, tb)result.Write(tb)return result.Bytes(), err}func (c *Client) Join() bool {join := NewPacket(c.nextInt(), MESSAGE_JOIN)join.AddTagInt32(TAG_CLIENTID, c.UserId)join.AddTagInt32(TAG_ROOMID, c.RoomId)b, err := join.Encode()//log.Printf("Send Hex %x %s", b, join.String())//conn.Write()_, err = c.session.Write(b)checkError("Join", err)return err != nil//b, err = readPacket(conn)//checkError(err)//if err != nil {//return false//}//join.Decode(b)//log.Printf("Recv Hex %x %s", b, join.String())//return true}func (c *Client) Handshake() bool {_, err := net.ResolveTCPAddr("tcp4", c.Address)checkError("Handshake ResolveTCPAddr", err)if err != nil {return false}conn, err := net.DialTimeout("tcp", c.Address, time.Second*30) //net.DialTCP("tcp", nil, tcpAddr)checkError("Handshake DialTimeout", err)if err != nil {return false}conn.(*net.TCPConn).SetKeepAlive(true)conn.(*net.TCPConn).SetNoDelay(true)c.session = connhandshake := NewHandshake(c.SecKey)b, err := handshake.Encode()_, err = conn.Write(b)//log.Printf("Send Hex %d %x %s", i, b, handshake.String())checkError("Handshake Write", err)b, err = readPacket(conn)checkError("Handshake Read", err)if err != nil {return false}handshake.Decode(b)//log.Printf("Recv Hex %x %s", b, handshake.String())c.logined = truego loop(conn)return true}func (c *Client) SendMessage(text string) bool {chat := NewPacket(c.nextInt(), MESSAGE_CHAT)chat.AddTagInt32(TAG_FROM, c.UserId)chat.AddTagInt32(TAG_TO, c.RoomId)chat.AddTagString(TAG_CONTENT, text)b, err := chat.Encode()//log.Printf("Send Hex %x %s", b, chat.String())_, err = c.session.Write(b)checkError("SendMessage Write", err)if err != nil {c.logined = false}return err != nil}func loop(conn net.Conn) {for {//conn.SetReadDeadline(time.Now().Add(time.Second * 90))b, err := readPacket(conn)checkError("Loop readPacket", err)if err != nil {break}pk := new(Packet)err = pk.Decode(b)checkError("Loop Decode", err)if err == nil {//log.Printf("Receive Hex %x %s", b, pk.String())} else {log.Printf("Receive Hex %x", b)}}log.Printf("Loop exit %+v/%+v", conn.LocalAddr(), conn.RemoteAddr())}// protocolpackage mainimport ("bytes""encoding/binary""fmt""log""math/rand""strconv""time")const (TAG_CODE     int32 = 0TAG_CLIENTID int32 = 1TAG_FROM     int32 = 2TAG_TO       int32 = 3TAG_ROOMID   int32 = 4TAG_CONTENT  int32 = 5 //stringTAG_ICON     int32 = 6 //string)const (MESSAGE_JOIN          int32 = 1MESSAGE_LEAVE         int32 = 2MESSAGE_CHAT          int32 = 3MESSAGE_USERLIST      int32 = 4ACK_MESSAGE           int32 = 0x0KEEPALIVE_MESSAGE     int32 = 111ACK_KEEPALIVE_MESSAGE int32 = 0x1111UNKNOWN_MESSAGE       int32 = 0x7474)type PacketEncodeError struct {Err string}func (e *PacketEncodeError) Error() string {return e.Err}type Handshake struct {PacketLength int32Random       int32Timestamp    int32Version      byteSignature    string //MD5(密鑰+yyyymmddhhMMss+Random+Version)}type TLV struct {Tag    int32Length int32Value  []byte}func NewTlv(tag int32, value string) *TLV {tlv := new(TLV)tlv.Tag = tagtlv.Value = []byte(value)tlv.Length = int32(len(tlv.Value))return tlv}func NewTlv1(tag int32, value int32) *TLV {tlv := new(TLV)tlv.Tag = tagbuf := bytes.NewBuffer(nil)binary.Write(buf, binary.BigEndian, &value)tlv.Value = buf.Bytes()tlv.Length = 4return tlv}func (p *TLV) Encode() []byte {buf := bytes.NewBuffer(nil)binary.Write(buf, binary.BigEndian, p.Tag)binary.Write(buf, binary.BigEndian, p.Length)buf.Write(p.Value)return buf.Bytes()}func (p *TLV) Decode(b []byte) error {return nil}type Packet struct {PacketLength int32Sequence     int32Timestamp    int32MessageType  int32Tags         []TLV}func NewPacket(seq int32, mtype int32) *Packet {packet := new(Packet)packet.Sequence = seqpacket.Timestamp = int32(time.Now().Unix())packet.MessageType = mtypepacket.Tags = make([]TLV, 0)return packet}func (p *Packet) Encode() ([]byte, error) {buf := bytes.NewBuffer(nil)err := binary.Write(buf, binary.BigEndian, p.Sequence)err = binary.Write(buf, binary.BigEndian, p.Timestamp)err = binary.Write(buf, binary.BigEndian, p.MessageType)for i := 0; i < len(p.Tags); i++ {tlv := p.Tags[i]buf.Write(tlv.Encode())}b := buf.Bytes()p.PacketLength = int32(len(b))buf = bytes.NewBuffer(nil)err = binary.Write(buf, binary.BigEndian, p.PacketLength)buf.Write(b)return buf.Bytes(), err}func (p *Packet) Decode(b []byte) error {buf := bytes.NewBuffer(nil)_, err := buf.Write(b)err = binary.Read(buf, binary.BigEndian, &p.PacketLength)if int32(len(b)) != p.PacketLength+4 {log.Printf("Invaild PacketLength %d/%d", len(b), p.PacketLength)buf = bytes.NewBuffer(nil)_, err = buf.Write(b)}err = binary.Read(buf, binary.BigEndian, &p.Sequence)err = binary.Read(buf, binary.BigEndian, &p.Timestamp)err = binary.Read(buf, binary.BigEndian, &p.MessageType)for len(buf.Bytes()) > 0 {var t, l int32binary.Read(buf, binary.BigEndian, &t)binary.Read(buf, binary.BigEndian, &l)if l > 4096 {log.Printf("Invaild Tag Length %d/%d", t, l)break}b := make([]byte, l)buf.Read(b)p.AddTag(TLV{t, l, b})}return err}func (p *Packet) AddTagString(tag int32, value string) {tlv := TLV{Tag: tag, Value: []byte(value)}tlv.Length = int32(len(tlv.Value))p.Tags = append(p.Tags, tlv)}func (p *Packet) AddTagInt32(tag int32, value int32) {tlv := TLV{Tag: tag, Length: 4}buf := bytes.NewBuffer(nil)binary.Write(buf, binary.BigEndian, &value)tlv.Value = buf.Bytes()p.Tags = append(p.Tags, tlv)}func (p *Packet) AddTag(tag TLV) {p.Tags = append(p.Tags, tag)}func (p *Packet) String() string {return fmt.Sprintf("Packet %+v", *p)}func NewHandshake(key string) *Handshake {handshake := new(Handshake)handshake.Random = rand.Int31()handshake.Timestamp = int32(time.Now().Unix())handshake.Version = 1handshake.Signature = MD5([]byte(key + strconv.FormatInt(int64(handshake.Timestamp), 10) + strconv.FormatInt(int64(handshake.Random), 10) + strconv.Itoa(int(handshake.Version))))//handshake.PacketLength = 4 + 4 + 1 + int32(len([]byte(handshake.Signature)))return handshake}func (p *Handshake) Encode() ([]byte, error) {buf := bytes.NewBuffer(nil)b := []byte(p.Signature)p.PacketLength = int32(len(b) + 9)err := binary.Write(buf, binary.BigEndian, p.PacketLength)err = binary.Write(buf, binary.BigEndian, p.Random)err = binary.Write(buf, binary.BigEndian, p.Timestamp)err = binary.Write(buf, binary.BigEndian, p.Version)_, err = buf.Write(b)return buf.Bytes(), err}func (p *Handshake) Decode(b []byte) error {if len(b) >= 50 {buf := bytes.NewBuffer(nil)_, err := buf.Write(b)err = binary.Read(buf, binary.BigEndian, &p.PacketLength)err = binary.Read(buf, binary.BigEndian, &p.Random)err = binary.Read(buf, binary.BigEndian, &p.Timestamp)err = binary.Read(buf, binary.BigEndian, &p.Version)p.Signature = string(buf.Bytes())//p.PacketLength = int32(len(b))return err}return &PacketEncodeError{"Invalid PakcetLength " + string(len(b))}}func (p *Handshake) String() string {return fmt.Sprintf("Handshake %+v", *p)}



轉載地址:http://www.oschina.net/code/snippet_874_17443

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.