protobuf 示例(php&golang)

個簡單的講,protobuf是相似於json和xml的一種序列化數據的方法,它比後二者更簡單、更快、序列化後的數據長度更短。php

 

這裏用作了一個php發送protobuf數據,用golang開發的server端接收數據的demo。git

注:github

本機已安裝好protobuf。golang

 

第一步,編寫pb文件

編寫一個簡單的pb文件,命名爲hello.proto,代碼內容爲:json

syntax = "proto3";
package lm;

message helloworld
{
    int32 id = 1; // ID
    string str = 2; // str
    int32 opt = 3; // optional field
}

第二步,編寫php發送端

  1. 切換到pb文件所在目錄,執行命令:
protoc --php_out=./ hello.proto

執行成功後,會生成相關基礎類文件。bash

   2.  新建一個發送端文件sender.php,經過socket發送內容給服務端。代碼內容爲:dom

<?php


include './GPBMetadata/Hello.php';
include './Lm/helloworld.php';

use Lm\helloworld;

$from = new helloworld();
$from->setId(1);
$from->setStr('窗前明月光,疑是地上霜。');
$from->setOpt(random_int(1000, 9999));

$data = $from->serializeToString();

$fp = fsockopen('127.0.0.1', 10011, $errno, $errmsg);

if (!$fp) {
    echo "error:\t" . $errmsg . "\n";
} else {
    fwrite($fp, $data);

    $answer = '';

    while (!feof($fp)) {
        $answer .= fgets($fp, 128);
    }

    fclose($fp);
    echo $answer . "\n";
}

 

第三步,使用go編寫服務端socket

  1. 執行命令,生成基礎文件:
    protoc --go_out=. *.proto
  2. 編寫server.go文件,監聽10011端口。代內容爲:
    package main
    
    import (
    	"log"
    	"net"
    	"protobufdemo/putils"
    	"time"
    )
    
    func main() {
    
    	addr := "localhost:10011"
    	// 建立socket文件描述符,綁定ip:port,改變socket狀態爲監聽狀態
    	ln, err := net.Listen("tcp", addr)
    	// 返回時關閉tcp鏈接
    	defer ln.Close()
    	if err != nil {
    		panic(err)
    	}
    	log.Println("begin listen on:", addr)
    	for {
    		// 從socket recive隊列裏獲取一個創建好的鏈接
    		conn, err := ln.Accept()
    		if err != nil {
    			panic(err)
    		}
    		// 新起一個goroutine處理鏈接
    		go handler(conn)
    	}
    }
    
    func handler(conn net.Conn) {
    	buffer := make([]byte, 2048) //創建一個slice
    	for {
    		n, err := conn.Read(buffer) //讀取客戶端傳來的內容
    		if err != nil {
    			log.Println(err)
    			return //當遠程客戶端鏈接發生錯誤(斷開)後,終止此協程。
    		}
    
    		dataReceived := string(buffer[:n])
    		log.Println(conn.RemoteAddr().String(), "receive data string:\n", dataReceived)
    
    		dataDecode, err := putils.DecodeData(dataReceived)
    
    		if err != nil {
    			log.Println(err)
    			return
    		}
    
    		log.Println(dataDecode.Id)
    		log.Println(dataDecode.Str)
    		log.Println(dataDecode.Opt)
    
    		//返回給客戶端的信息
    		strTemp := "CofoxServer got msg \"" + string(buffer[:n]) + "\" at " + time.Now().String()
    		conn.Write([]byte(strTemp))
    
    		// 關閉鏈接
    		conn.Close()
    		break
    	}
    
    }

    其中DecodeData方法內容:tcp

    package putils
    
    import (
    	"github.com/golang/protobuf/proto"
    	"protobufdemo/lm"
    )
    
    func DecodeData(data string) (*lm.Helloworld, error) {
    
    	result := &lm.Helloworld{}
    	err := proto.Unmarshal([]byte(data), result)
    
    	return result, err
    }
相關文章
相關標籤/搜索