void DataSocket::postDisConnect() { if (mEventLoop != nullptr) { DataSocket::PTR tmp = this; mEventLoop->pushAsyncProc([=](){ tmp->procCloseInLoop(); }); } }
void SSDBMultiClient::sendPing(DataSocket::PTR ds) { DBServerUserData* dbUserData = (DBServerUserData*)ds->getUserData(); if (dbUserData->pingTime > 0) { SSDBProtocolRequest sr; sr.init(); sr.appendStr("ping"); sr.endl(); ds->send(sr.getResult(), sr.getResultLen()); /*自动发送的ping操作,也要模拟一个完成回调,不然会导致业务上的请求乱序*/ queue<std::function<void(const string& response)>>* callbacklist = dbUserData->callbacklist; callbacklist->push(nullptr); dbUserData->pingTimer = mNetService.getTimerMgr().AddTimer(dbUserData->pingTime, [this, ds](){ sendPing(ds); }); } }
void SSDBMultiClient::startNetThread(std::function<void(void)> frameCallback) { if (mNetThread == nullptr) { mRunIOLoop = true; mNetThread = new thread([&, frameCallback](){ while (mRunIOLoop) { mNetService.loop(1); mRequestList.SyncRead(0); RequestMsg tmp; while (mRequestList.PopFront(&tmp)) { if (!mBackends.empty()) { /* 随机选择一个服务器 */ DataSocket::PTR client = mBackends[rand() % mBackends.size()]; DBServerUserData* dbUserData = (DBServerUserData*)client->getUserData(); queue<std::function<void(const string& response)>>* callbacklist = dbUserData->callbacklist; callbacklist->push(tmp.callback); client->send(tmp.content.c_str(), tmp.content.size()); } else { forgeError("no server", tmp.callback); } } mLogicFunctorMQ.ForceSyncWrite(); /* TODO::目前只在通知队列里有数据时,才调用帧回调--可在其中唤醒主线程--就无需把外部mainloop设置到此类 */ if (mLogicFunctorMQ.SharedListSize() > 0 && frameCallback != nullptr) { frameCallback(); } } }); } }
int main(int argc, char** argv) { if (argc != 5) { fprintf(stderr, "Usage: <server ip> <server port> <session num> <packet size>\n"); exit(-1); } std::string ip = argv[1]; int client_num = atoi(argv[2]); int packet_len = atoi(argv[3]); int port_num = atoi(argv[4]); ox_socket_init(); EventLoop mainLoop; /* 客户端IO线程 */ std::thread* ts = new std::thread([&mainLoop, client_num, packet_len, port_num, ip]{ printf("start one client thread \n"); /* 客户端eventloop*/ EventLoop clientEventLoop; char* senddata = (char*)malloc(packet_len); /* 消息包大小定义 */ atomic_llong packet_num = ATOMIC_VAR_INIT(0); atomic_llong total_recv = ATOMIC_VAR_INIT(0); TimerMgr tm; for (int i = 0; i < client_num; i++) { int client = ox_socket_connect(ip.c_str(), port_num); ox_socket_nodelay(client); DataSocket::PTR pClient = new DataSocket(client, 1024 * 1024); pClient->setEnterCallback([&](DataSocket::PTR ds){ LongPacket sp(1); sp.writeINT64((int64_t)ds); sp.writeBinary(senddata, packet_len); for (int i = 0; i < 1; ++i) { ds->send(sp.getData(), sp.getLen()); } /* 可以放入消息队列,然后唤醒它主线程的eventloop,然后主线程通过消息队列去获取*/ ds->setDataCallback([&total_recv, &packet_num](DataSocket::PTR ds, const char* buffer, size_t len){ const char* parse_str = buffer; int total_proc_len = 0; int left_len = len; while (true) { bool flag = false; if (left_len >= sizeof(sizeof(uint16_t) + sizeof(uint16_t))) { ReadPacket rp(parse_str, left_len); uint16_t packet_len = rp.readINT16(); if (left_len >= packet_len && packet_len >= (sizeof(uint16_t) + sizeof(uint16_t))) { total_recv += packet_len; packet_num++; ReadPacket rp(parse_str, packet_len); rp.readINT16(); rp.readINT16(); int64_t addr = rp.readINT64(); if (addr == (int64_t)(ds)) { ds->send(parse_str, packet_len); } total_proc_len += packet_len; parse_str += packet_len; left_len -= packet_len; flag = true; } } if (!flag) { break; } } return total_proc_len; }); ds->setDisConnectCallback([](DataSocket::PTR arg){ delete arg; }); }); clientEventLoop.pushAsyncProc([&, pClient](){ if (!pClient->onEnterEventLoop(&clientEventLoop)) { delete pClient; } }); } int64_t now = ox_getnowtime(); while (true) { clientEventLoop.loop(tm.NearEndMs()); tm.Schedule(); if ((ox_getnowtime() - now) >= 1000) { cout << "total recv:" << (total_recv / 1024) / 1024 << " M /s" << " , num " << packet_num << endl; now = ox_getnowtime(); total_recv = 0; packet_num = 0; } } }); ts->join(); }
void SSDBMultiClient::addConnection(sock fd, string ip, int port, int pingTime, bool isAutoConnection) { ox_socket_nodelay(fd); DataSocket::PTR ds = new DataSocket(fd, 32 * 1024 * 1024); DBServerUserData* dbUserData = new DBServerUserData; dbUserData->ip = ip; dbUserData->port = port; dbUserData->pingTime = pingTime; dbUserData->isAutoConnection = isAutoConnection; dbUserData->callbacklist = new queue<std::function<void(const string& response)>>(); dbUserData->p = parse_tree_new(); ds->setUserData((int64_t)dbUserData); ds->setEnterCallback([this](DataSocket::PTR ds){ DBServerUserData* dbUserData = (DBServerUserData*)ds->getUserData(); mBackends.push_back(ds); ds->setCheckTime(dbUserData->pingTime); sendPing(ds); }); ds->setDataCallback([&](DataSocket::PTR ds, const char* buffer, size_t len){ const char* parse_str = buffer; DBServerUserData* dbUserData = (DBServerUserData*)ds->getUserData(); while (parse_str < (buffer + len)) { /* TODO::检测是否redis协议, 并编写redis reply到ssdb reply的转换 */ char c = parse_str[0]; int packet_len = 0; if (c == '+' || c == '-' || c == ':' || c == '$' || c == '*') { if (dbUserData->p == nullptr) { dbUserData->p = parse_tree_new(); } char* parseEndPos = (char*)parse_str; int parseRet = parse(dbUserData->p, &parseEndPos, (char*)buffer + len); if (parseRet == REDIS_OK) { packet_len = (parseEndPos - parse_str); } else if (parseRet == REDIS_RETRY) { } else { assert(false); } parse_tree_del(dbUserData->p); dbUserData->p = nullptr; } else { packet_len = SSDBProtocolResponse::check_ssdb_packet(parse_str, (len - (parse_str - buffer))); } if (packet_len > 0) { /* 取出等待的异步回调,并将response附加给它,再投递给逻辑线程去执行 */ queue<std::function<void(const string& response)>>* callbacklist = dbUserData->callbacklist; assert(!callbacklist->empty()); if (!callbacklist->empty()) { auto& callback = callbacklist->front(); if (callback != nullptr) { std::shared_ptr<string > response = std::make_shared<string>(parse_str, packet_len); mLogicFunctorMQ.Push([callback, response](){ callback(*response); }); } callbacklist->pop(); } parse_str += packet_len; } else { break; } } return parse_str - buffer; }); ds->setDisConnectCallback([&](DataSocket::PTR arg){ DBServerUserData* dbUserData = (DBServerUserData*)arg->getUserData(); queue<std::function<void(const string& response)>>* callbacklist = dbUserData->callbacklist; while (!callbacklist->empty()) { forgeError("server close", callbacklist->front()); callbacklist->pop(); } cout << "disconnect of " << dbUserData->ip << " port " << dbUserData->port << endl; if (dbUserData->isAutoConnection) { asyncConnection(dbUserData->ip, dbUserData->port, dbUserData->pingTime, dbUserData->isAutoConnection); } Timer::Ptr timer = dbUserData->pingTimer.lock(); if (timer != nullptr) { timer->Cancel(); } delete dbUserData->callbacklist; if (dbUserData->p != nullptr) { parse_tree_del(dbUserData->p); } delete dbUserData; for (size_t i = 0; i < mBackends.size(); ++i) { if (mBackends[i] == arg) { mBackends.erase(mBackends.begin() + i); } } delete arg; }); mNetService.pushAsyncProc([&, ds](){ if (!ds->onEnterEventLoop(&mNetService)) { delete ds; } }); }