HandlerSocke源码t自带C++客户端的so库以及c++例子(和下面的第一个基本一样),只不过没什么具体的文档介绍,于是给个例子(可以看一下安装包里的协议说明,更容易理解)
//====================================== // Name : hsTest.cpp // Author : asyty // Version : // Copyright : Your copyright notice // Description : hsClient //====================================== #include#include #include using namespace dena; using namespace std; int main() { /*********创建client***********/ config conf; conf["host"] = "127.0.0.1"; conf["port"] = "9998"; socket_args sock_args; sock_args.set(conf); hstcpcli_ptr cli = hstcpcli_i::create(sock_args); /*******通过索引打开连接 ************/ int code = 0; size_t numflds = 0; //写请求buffer,column之间除了逗号不允许空格,通过下面的request_send发送请求 // db name // table // index cli->request_buf_open_index(1, "test", "table", "index_1", "colum1,colum2"); do { //发送request_buf_open_index请求 if (cli->request_send() != 0) { fprintf(stderr, "request_send: %s\n", cli->get_error().c_str()); break; } if ((code = cli->response_recv(numflds)) != 0) { fprintf(stderr, "response_recv: %s\n", cli->get_error().c_str()); break; } } while (false); cli->response_buf_remove(); /*********获取数据************/ char key_buf[32] = { 0 }; uint32_t uid = 2; snprintf(key_buf, 32, "%u", uid); const string key(key_buf); const string_ref keyref(key.data(), key.size()); const string kTestEqualOp("="); const string_ref kTestEqualOpRef(kTestEqualOp.data(), kTestEqualOp.size()); cli->request_buf_exec_generic(1, kTestEqualOpRef, &keyref, 1, 0, 0, string_ref(), 0, 0); do {//发送request_buf_exec_generic if (cli->request_send() != 0) { fprintf(stderr, "request_send: %s\n", cli->get_error().c_str()); break; } if ((code = cli->response_recv(numflds)) != 0) { fprintf(stderr, "response_recv: %s\n", cli->get_error().c_str()); break; } while (true) { const string_ref * const row = cli->get_next_row(); if (row == 0) { break; } for (size_t i = 0; i < numflds; ++i) { const string val(row[i].begin(), row[i].size()); printf(" %s", val.c_str()); } printf("\n"); } } while (false); cli->response_buf_remove(); cli->close() return 0; }
对于多线程的使用,hstcpcli_i这个结构体部分结构如下
namespace dena { struct hstcpcli : public hstcpcli_i, private noncopyable { hstcpcli(const socket_args& args); virtual void close(); virtual int reconnect(); ................ virtual int request_send(); virtual int response_recv(size_t& num_flds_r); ................ private: int read_more(); void clear_error(); int set_error(int code, const std::string& str); private: auto_file fd; socket_args sargs; string_buffer readbuf; string_buffer writebuf; size_t response_end_offset; /* incl newline */ size_t cur_row_offset; size_t num_flds; size_t num_req_bufd; /* buffered but not yet sent */ size_t num_req_sent; /* sent but not yet received */ size_t num_req_rcvd; /* received but not yet removed */ int error_code; std::string error_str; std::vectorflds; };
它其实就是socket客户端,有两个string buffer 一个负责存发送数据 一个负责接收数据,如果多个请求同时发送,接收数据就会各种混乱出错。。。所以 它本身是不支持并发的,除非自己写代码控制并发。。。
因此 多线程的操作应该使用不同的hstcpcli,open index时可以使用相同的index_id
//============================================================================ // Name : hsMultiTest.cpp // Author : asyty // Version : // Copyright : Your copyright notice // Description : multithread test //============================================================================ #include#include #include #include using namespace dena; using namespace std; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int pthread_id = 1; void* cli_thread(void *args) { pthread_mutex_lock(&mutex); int tid = pthread_id; pthread_id++; pthread_mutex_unlock(&mutex); config conf; conf["host"] = "127.0.0.1"; conf["port"] = "9998"; socket_args sock_args; sock_args.set(conf); hstcpcli_ptr cli = hstcpcli_i::create(sock_args); int code = 0; size_t numflds = 0; cli->request_buf_open_index(tid, "test", "table", "PRIMARY", "colum2,colum3"); do { if (cli->request_send() != 0) { fprintf(stderr, "request_send: %s\n", cli->get_error().c_str()); cli->close(); pthread_exit(NULL); } if ((code = cli->response_recv(numflds)) != 0) { fprintf(stderr, "response_recv: %s\n", cli->get_error().c_str()); cli->close(); pthread_exit(NULL); } } while (false); cli->response_buf_remove(); char key_buf[32] = { 0 }; uint32_t uid = 0; const string kTestEqualOp("="); const string_ref kTestEqualOpRef(kTestEqualOp.data(), kTestEqualOp.size()); for (uid = 1000 * tid + 1; uid <= 1000 * tid + 1000; uid++) { snprintf(key_buf, 32, "%u", uid); const string key(key_buf); const string_ref keyref(key.data(), key.size()); cli->request_buf_exec_generic(tid, kTestEqualOpRef, &keyref, 1, 0, 0, string_ref(), 0, 0); do { if (cli->request_send() != 0) { fprintf(stderr, "request_send: %s\n", cli->get_error().c_str()); break; } if ((code = cli->response_recv(numflds)) != 0) { fprintf(stderr, "response_recv: %s\n", cli->get_error().c_str()); break; } while (true) { const string_ref * const row = cli->get_next_row(); if (row == 0) { break; } for (size_t i = 0; i < numflds; ++i) { const string val(row[i].begin(), row[i].size()); printf(" %s", val.c_str()); } printf("\n"); } } while (false); cli->response_buf_remove(); } cli->close(); } int main(int argc, char** argv) { pthread_t *id; int tid, ret, ths; struct timeval start, end; if(argc < 2) return 0; ths = atoi(argv[1]); if(ths <= 0) return 0; id = new pthread_t[ths]; for (tid = 1; tid <= ths; tid++) { ret = pthread_create(&id[tid], NULL, cli_thread, (void*) &tid); if (ret != 0) { printf("Create pthread error!\n"); } else { printf("create pthread %d\n", tid); } usleep(1000); } printf("This is the main process.\n"); for (tid = 0; tid < ths; tid++) { pthread_join(id[tid], NULL); } delete[] id; return 0; }
C++客户端和JAVA客户端(某淘宝人士开发的hs4j)相比,连接延时几乎可以忽略不计,在同样的机器上测试并发,在1000并发数下,java客户端读取性能能飙到15万/秒,C++能达到40万/秒,性能相差还是很大的,只不过hs4j用起来更方便
转载请注明源
http://asyty.iteye.com/blog/1556070