firefly学习笔记之C客户端与Python服务器交互(3)

来源:互联网 发布:js获取application值 编辑:程序博客网 时间:2024/06/05 05:52

       这一章介绍现在比较流行的通信格式Protocol Buffer。

     4.PB (Protocol Buffer解析)

   ProtocolBuffer是用于结构化数据串行化的灵活,高效,自动的方法,有如XML,JSON.不过它更小,更快,也更简单,你可以定义自  己的数据机构,然后使用代码生成器生成的代码来读写这个数据结构。不过注意一下,protocol buffer的proto文件你要是用string类型,那么你在c++中用的是utf-8,在java和python中必须用unicode。

teststruct.proto

option optimize_for = LITE_RUNTIME; //最优编码message Person {    required string name = 1;  //用户名  required int32 id = 2;  //用户id  optional string email = 3;  //email    //号码类型枚举  enum PhoneType {      MOBILE = 0;      HOME = 1;      WORK = 2;    }      message PhoneNumber {  
    required string number = 1;  //号码    optional PhoneType type = 2 [default = HOME];  //号码类型  }      required int32 phonecnt = 4;//号码数量  repeated PhoneNumber phone = 5;  //号码[packed=true]用于优化,只能用于原始的几个类型}    message AddressBook {  required int32  personcnt = 1;//玩家数量    repeated Person person = 2;  //玩家信息
}  

client.cpp

// testPython2.cpp : Defines the entry point for the console application.//// testpython.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <Windows.h>#include <string>#include "teststruct.pb.h"using namespace std;#pragma comment(lib,"ws2_32.lib")#pragma pack(push)#pragma pack(1)struct sTest{int id;char szName[10];};#pragma pack(pop)//iconv也行string Utf8ToGBK(string str){...
}string GBKToUTF8(string str){
...}string  ConvertAddressBookToString(){//转换pbtostringAddressBook addressbook;addressbook.set_personcnt(2);//repeat 对象,数组addPerson *pInfo1 = addressbook.add_person();pInfo1->set_id(111);pInfo1->set_name(GBKToUTF8("天下").c_str());pInfo1->set_email("xx@163.com");pInfo1->set_phonecnt(2);//repeat数组Person_PhoneNumber*pNumber1 = pInfo1->add_phone();pNumber1->set_type(Person_PhoneType_HOME);pNumber1->set_number("187XXXXXX");pNumber1 = pInfo1->add_phone();pNumber1->set_type(Person_PhoneType_MOBILE);pNumber1->set_number("178XXXXX");pInfo1 = addressbook.add_person();pInfo1->set_id(112);pInfo1->set_name(GBKToUTF8("天下x").c_str());pInfo1->set_email("xxx@163.com");pInfo1->set_phonecnt(1);//repeat数组pNumber1 = pInfo1->add_phone();pNumber1->set_type(Person_PhoneType_HOME);pNumber1->set_number("1587XXXXXX");string str;addressbook.SerializeToString(&str);return str;}void ConvertStringToPB(char* str,int size){AddressBook address;address.ParseFromArray(str,size);//解析printf("address person cnt :%d\n",address.personcnt());printf("______________________________person data_______________________\n");//repeat指针访问//RepeatedPtrField<Person*> *pPersonInfo = address.mutable_person();////if (pPersonInfo == NULL)//return;//RepeatedPtrField<Person*>::iterator it = pPersonInfo->begin();//while(it != pPersonInfo->end());//{//printf("person id:%d\n",it->id());//printf("person name:%s\n",it->name().c_str());//if (it->has_email())//{//printf("person email:%s\n",it->email().c_str());//}//printf("person numbercnt:%d\n",id->phonecnt());//RepeatedPtrField<Person_PhoneNumber*> *pPhone = id->mut//}for (int i = 0 ; i < address.personcnt();++i){Person *pPersonInfo = address.mutable_person(i);if (pPersonInfo){printf("person id:%d\n",pPersonInfo->id());printf("person name:%s\n",Utf8ToGBK(pPersonInfo->name().c_str()).c_str());if (pPersonInfo->has_email()){printf("person email:%s\n",pPersonInfo->email().c_str());}printf("person number cnt:%d\n",pPersonInfo->phonecnt());printf("______________________________phone data_______________________\n");for (int j = 0; j < pPersonInfo->phonecnt();++j){Person_PhoneNumber *pNumber = pPersonInfo->mutable_phone(j);if (pNumber){printf("person phone number:%s\n",pNumber->number().c_str());printf("person phone type:%d\n",pNumber->type());}}printf("______________________________phone data_______________________\n");}}printf("______________________________person data_______________________\n");}int _tmain(int argc, _TCHAR* argv[]){WSADATA wd;WSAStartup(MAKEWORD(2,2),&wd);SOCKET client = socket(AF_INET,SOCK_STREAM,0);if (client == SOCKET_ERROR){printf("error:%d\n",WSAGetLastError());exit(0);}SOCKADDR_IN addr;addr.sin_family = AF_INET;addr.sin_port = htons(8877);addr.sin_addr.s_addr  = inet_addr("127.0.0.1");int ret = connect(client,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));if (ret != 0){printf("error:%d\n",WSAGetLastError());exit(0);}string str = ConvertAddressBookToString();printf("%s\n",str.c_str());int sendsize = send(client,str.c_str(),str.length(),0);if (sendsize == 0){printf("error:%d\n",WSAGetLastError());exit(0);}char szBuf[1024] = {0};int recvdata = recv(client,szBuf,1024,0);szBuf[recvdata] = '\0';printf("recvdata:%d\n",recvdata);ConvertStringToPB(szBuf,recvdata-1);WSACleanup();system("pause");return 0;}


python server.py

#coding:utf8'''@author: Administrator'''import teststruct_pb2;import socket;import sys;#datatopbdef PaseStringToPB(data):    address = teststruct_pb2.AddressBook();    address.ParseFromString(data);           cnt = address.personcnt;        print "number of person:%d"%(cnt);         #循环每个玩家    for person in address.person:        print "person id:",person.id;        print "person name:",person.name;                #optional不一定存在        if person.HasField("email"):            print "person name email:",person.email;                print "person has number cnt:",person.phonecnt;                #循环遍历每一个phone        for phone in person.phone:            if phone.type == teststruct_pb2.Person.MOBILE:                print "person phone type: MOBILE";            elif phone.type == teststruct_pb2.Person.WORK:                print "person phone type: WORK";            elif phone.type == teststruct_pb2.Person.HOME:                print "person phone type: HOME";            else:                print "person phone tpye: NONE";                            print "person phone number:",phone.number;                    if __name__ == "__main__":    host = "127.0.0.1";    port = 8877;    addr = (host,port);        #socket created     try:        server = socket.socket(socket.AF_INET,socket.SOCK_STREAM);    except socket.error,msg:        print "socket created failed ! errno:" + str(msg[0]) + " errmsg:" + str(msg[1]);        sys.exit();    else:        print "socket create sucesss!";    #bind    try:        server.bind(addr);    except socket.error,msg:        print "socket bind failed ! errno:" + str(msg[0]) + " errmsg:" + str(msg[1]);        sys.exit();    else:        print "socket bind success!";            #listen    server.listen(10);        while True:        client,caddr = server.accept();                print caddr;                recvdata = client.recv(1024);                #string to pb        PaseStringToPB(recvdata);                        #pbtostring        address = teststruct_pb2.AddressBook();                address.personcnt = 2;                #repeat add 类似一个数组        person1 = address.person.add();                person1.id = 123;                namestr = "张三";        person1.name = namestr.decode("utf-8");                person1.email = "111@163.com";                person1.phonecnt = 1;        phone1 = person1.phone.add();        phone1.type = teststruct_pb2.Person.MOBILE;        phone1.number = "187XXXXXXX";                person2 = address.person.add();        person2.id = 123;                namestr = "李四";        person2.name = namestr.decode("utf-8");                person2.email = "111@163.com";                person2.phonecnt = 1;        phone2 = person2.phone.add();        phone2.type = teststruct_pb2.Person.WORK;        phone2.number = "187XXXXXXX";                ##序列化        message = address.SerializeToString();                print message;                client.sendall(message);                print len(message);                    client.close();    server.close();
几种常用的通信格式都介绍完,在后面的firefly练习中,也会用赶流行的用PB,来作为数据交互格式!
       
0 0
原创粉丝点击