个简单的讲,protobuf是类似于json和xml的一种序列化数据的方法,它比后两者更简单、更快、序列化后的数据长度更短。
这里用做了一个php发送protobuf数据,用golang开发的server端接收数据的demo。
注:
本机已安装好protobuf。
第一步,编写pb文件
编写一个简单的pb文件,命名为hello.proto,代码内容为:
syntax = "proto3";
package lm;
message helloworld
{
int32 id = 1; // ID
string str = 2; // str
int32 opt = 3; // optional field
}
第二步,编写php发送端
切换到pb文件所在目录,执行命令:
protoc --php_out=./ hello.proto
执行成功后,会生成相关基础类文件。
2. 新建一个发送端文件sender.php,通过socket发送内容给服务端。代码内容为:
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编写服务端
执行命令,生成基础文件: protoc --go_out=. *.proto
编写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方法内容: 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
}