python 和 c++ 之间发消息用json

来源:互联网 发布:淘宝 买家秀图 编辑:程序博客网 时间:2024/05/31 15:19

这段代码是py发给c++的一个消息包,包里含json字符串,没有c++返回的过程!

-------------------

因为工作需要...中间省略5000字,所以用c++做的服务器,收发消息需要用json来打包并解析消息。
我以前收发消息都是结构体直接强转,所以这也是第一次,发个帖子上来,希望对有的朋友有帮助。
-------------------
先说python,这个语言一直想学,这段时间学了个把星期,发现测试的确非常方便,总比用c++写测试代码好多了,用c++写测试代码的那个蛋疼,py几行代码就搞到了。
准备发上py代码,这之前先做一个大概的说明,这段py代码不是纯粹的发一条json消息,还附带了一个简单的tcp socket的并发连接测试代码,也就是创建N个线程去connect服务器,不需要的自己过滤吧。这段代码用了py的那个好像叫装饰器的东西,就是@这个,不明白的朋友可以百度,简单的来说,我的这个装饰器就是用来统计时间的。

__author__ = 'Administrator'import socketimport jsonimport threadingimport datetimeimport structdef get_execute_time_p2(f):    def inner(p1=None, p2=None):        begin = datetime.datetime.now().microsecond        f(p1, p2)        end = datetime.datetime.now().microsecond        print("{0} execute time is {1}".format(f.__name__, end-begin))        return f    return innerdef get_execute_time_p1(f):    def inner(p1=None):        begin = datetime.datetime.now().microsecond        f(p1)        end = datetime.datetime.now().microsecond        print("{0} execute time is {1}".format(f.__name__, end-begin))        return f    return innerdef get_socket():    host = "localhost"    port = 8001    address = (host, port)    tcp_socket_temp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    tcp_socket_temp.settimeout(2)    tcp_socket_temp.connect(address)    return tcp_socket_temp@get_execute_time_p1def test_accept(cnt):    print("thread launched.")    ok__ = 0    for xer34 in range(cnt):        try:            sd2342 = get_socket()            # input("enter any key to continue...")            sd2342.close()            ok__ += 1            # print(xer34, end="  ")            # if xer34 % 30 == 0:            #     print("")   # C R L F        except Exception as e:            print(e)    print("connect svr success cnt is {0}".format(ok__))@get_execute_time_p2def create_thread_to_test_accept(thread_count, con_cnt_every_thread):    for x342df in range(thread_count):        thread = threading.Thread(None, test_accept, "test_accept", (con_cnt_every_thread,))        thread.start()def print_binary(number):    for sda24 in range(32):        if number & (1 << sda24):            print(1, end="")        else:            print(0, end="")        if (sda24 + 1) % 8 == 0:            print(" ", end="")data_list_child = []for cnt in range(3):    data_list_child.append({"_f": 123.123, "_long_id": "1234567890123456789"})data_list = {"_msg_enum": 0, "_buffer": "abcdefg", "_element_len": 3, "_element": data_list_child}data_json = json.dumps(data_list)print(data_list)print(len(data_json), data_json)# use 4 threads and every thread executes 10000 connections test to connect svr# test OK!# create_thread_to_test_accept(4, 50000)my_fmt = "i{0}s".format(len(data_json))print(my_fmt)send_string = struct.pack(my_fmt, 4 + len(data_json), bytes(data_json, "utf8"))print(send_string, type(send_string))a1, a2 = struct.unpack(my_fmt, send_string)print(a1, a2)tmp_socket = get_socket()tmp_socket.send(send_string)input("enter 'enter' to close socket and quit.")tmp_socket.close()

使用的py3,运行结果差点忘记了,如下:

E:\Python34\python.exe E:/PycharmProjects/study/resource-svr-test.py
{'_msg_enum': 0, '_element_len': 3, '_buffer': 'abcdefg', '_element': [{'_long_id': '1234567890123456789', '_f': 123.123}, {'_long_id': '1234567890123456789', '_f': 123.123}, {'_long_id': '1234567890123456789', '_f': 123.123}]}
227 {"_msg_enum": 0, "_element_len": 3, "_buffer": "abcdefg", "_element": [{"_long_id": "1234567890123456789", "_f": 123.123}, {"_long_id": "1234567890123456789", "_f": 123.123}, {"_long_id": "1234567890123456789", "_f": 123.123}]}
i227s
b'\xe7\x00\x00\x00{"_msg_enum": 0, "_element_len": 3, "_buffer": "abcdefg", "_element": [{"_long_id": "1234567890123456789", "_f": 123.123}, {"_long_id": "1234567890123456789", "_f": 123.123}, {"_long_id": "1234567890123456789", "_f": 123.123}]}' <class 'bytes'>
231 b'{"_msg_enum": 0, "_element_len": 3, "_buffer": "abcdefg", "_element": [{"_long_id": "1234567890123456789", "_f": 123.123}, {"_long_id": "1234567890123456789", "_f": 123.123}, {"_long_id": "1234567890123456789", "_f": 123.123}]}'
enter 'enter' to close socket and quit.

Process finished with exit code 0
或许你看到了在大括号“{”前面的227,这个227是一个完整的消息包的一部分,但是不属于json的一部分,这个227表示整个包的大小,做tcp socket的应该都知道,这个协议收到的包是要自己拆粘的。包的格式是:
{int, char[]}。

-----------------

以上py的已经说完了,下面说c++的代码,c++用的jsoncpp解析的,这个使用非常简单,这里只传上解析的过程, 因为c++的代码太多.下面第一部分代码是从消息包里解析出json,1:

static Json::Reader _g_this_reader;void DoClientReq::Do(__cr_phd_ptr phd){/* 包头定义包的长度,该定义不属于json需要解析的范围 */Json::Value value;char* buffer = phd->_buffer.Get() + HEADSIZE;_g_this_reader.parse(buffer, buffer + phd->_offset, value);do_client_req(value);}
第二部分是获取json里的内容,内容涵盖了int, int64, float/double, char[], 以及结构体里的数组信息等:

void DoClientReq::do_client_req(const Json::Value& value){if (value.empty() || !value.isMember("_msg_enum")){return;}eProtocol e = (eProtocol)value["_msg_enum"].asInt();switch (e){case eProtocol::_req_test:/* 227 {"_buffer": "abcdefg", "_element_len": 3, "_msg_enum": 0, "_element": [{"_f": 123.123, "_long_id": "1234567890123456789"}, {"_f": 123.123, "_long_id": "1234567890123456789"}, {"_f": 123.123, "_long_id": "1234567890123456789"}]} *//*  *227  *{"_buffer": "abcdefg", "_element_len": 3, "_msg_enum": 0,  *"_element": \ *[{"_f": 123.123, "_long_id": "1234567890123456789"},  *{"_f": 123.123, "_long_id": "1234567890123456789"},  *{"_f": 123.123, "_long_id": "1234567890123456789"}]} */{printf("\n-------------------JSON TEST BEGIN-----------------------------\n");printf("_msg_enum(int):%d\n", value["_msg_enum"].asInt());printf("_buffer(char[]):%s\n", value["_buffer"].asCString());printf("_element_len(int):%d\n", value["_element_len"].asInt());Json::Value child = value["_element"];for (int i = 0; i < value["_element_len"].asInt(); i++){printf("_element(array):\n");printf("\t_element::_long_id(int64):%lld\n", _atoi64(child[i]["_long_id"].asCString()));printf("\t_element::_f(double/float):%f\n", child[i]["_f"].asDouble());}printf("-------------------JSON TEST END-------------------------------\n");}break;default:break;}}

下面附上c++解析的结果:

-------------------JSON TEST BEGIN-----------------------------
_msg_enum(int):         0
_buffer(char[]):        abcdefg
_element_len(int):      3
_element(array):
        _element::_long_id(int64):      1234567890123456789
        _element::_f(double/float):     123.123000
_element(array):
        _element::_long_id(int64):      1234567890123456789
        _element::_f(double/float):     123.123000
_element(array):
        _element::_long_id(int64):      1234567890123456789
        _element::_f(double/float):     123.123000
-------------------JSON TEST END-------------------------------


或许你看到了解析int64的过程,我发现,py如果发字符串"12345678901234567890"20个字符给c++解析成int64的时候,会出问题,解析的不对,没有报错。

如果去掉最后一个0,则解析成功,难道19位数字是有符号int64的最大数字长度?如果有朋友了解,麻烦回复下,谢谢!以便我日后参考以及留给他人。






0 0
原创粉丝点击