void O2Client:: NetIOThread(void) { O2SocketSessionPListIt ssit; int lasterror; while (Active) { // Signal Off SessionListLock.Lock(); { if (sss.empty()) SessionExistSignal.Off(); } SessionListLock.Unlock(); // Wait SessionExistSignal.Wait(); if (!Active) break; // Setup FD fd_set readfds; fd_set writefds; FD_ZERO(&readfds); FD_ZERO(&writefds); SessionListLock.Lock(); { for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; if (ss->can_send) FD_SET(ss->sock, &writefds); if (ss->can_recv) FD_SET(ss->sock, &readfds); } } SessionListLock.Unlock(); // select struct timeval tv; tv.tv_sec = SELECT_TIMEOUT_MS/1000; tv.tv_usec = SELECT_TIMEOUT_MS%1000; select(0, &readfds, &writefds, NULL, &tv); if (!Active) break; // // 既存セッションとの送受信 // SessionListLock.Lock(); ssit = sss.begin(); SessionListLock.Unlock(); while (Active) { bool end = false; SessionListLock.Lock(); { if (ssit == sss.end()) end = true; } SessionListLock.Unlock(); if (end) break; O2SocketSession *ss = *ssit; // IP文字列 wstring ipstr; if (O2DEBUG) ulong2ipstr(ss->ip, ipstr); else ip2e(ss->ip, ipstr); // Send if (FD_ISSET(ss->sock, &writefds)) { int len; const char *buff = ss->GetNextSend(len); if (len > 0) { int n = send(ss->sock, buff, len, 0); if (n > 0) { ss->UpdateSend(n); ss->UpdateTimer(); SendByte += n; OnSend(ss); if (hwndSetIconCallback) { #if defined(_WIN32) && !defined(__WXWINDOWS__) /** Use ordinary windows api */ PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0); #else /** Platform is not windows */ #warning "TODO: implement wxWidgets event method here" #endif } } else if (n == 0) { // do nothing } #ifdef _WIN32 /** Windows */ else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) #else /** Unix */ else if (errno == EAGAIN) #endif { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"送信エラー(%d)", lasterror); } ss->error = true; ss->Deactivate(); } } } // Recv if (FD_ISSET(ss->sock, &readfds)) { char buff[RECVBUFFSIZE]; int n = recv(ss->sock, buff, RECVBUFFSIZE, 0); if (n > 0) { ss->AppendRecv(buff, n); ss->UpdateTimer(); RecvByte += n; OnRecv(ss); if (hwndSetIconCallback) { #if defined(_WIN32) && !defined(__WXWINDOWS__) /** Use ordinary windows api */ PostMessage(hwndSetIconCallback, msgSetIconCallback, 0, 0); #else /** Platform is not windows */ #warning "TODO: implement wxWidgets event method here" #endif } } else if (n == 0) { /*if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"受信0"); }*/ ss->Deactivate(); } #ifdef _WIN32 /** Windows */ else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) #else /** Unix */ else if (errno == EAGAIN) #endif { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"受信エラー(%d)", lasterror); } ss->error = true; ss->Deactivate(); } }
void O2Client:: NetIOThread(void) { O2SocketSessionPListIt ssit; int lasterror; while (Active) { // Signal Off SessionListLock.Lock(); { if (sss.empty()) SessionExistSignal.Off(); } SessionListLock.Unlock(); // Wait SessionExistSignal.Wait(); if (!Active) break; // Setup FD fd_set readfds; fd_set writefds; FD_ZERO(&readfds); FD_ZERO(&writefds); SessionListLock.Lock(); { for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; if (ss->can_send) FD_SET(ss->sock, &writefds); if (ss->can_recv) FD_SET(ss->sock, &readfds); } } SessionListLock.Unlock(); // select struct timeval tv; tv.tv_sec = SELECT_TIMEOUT_MS/1000; tv.tv_usec = SELECT_TIMEOUT_MS%1000; select(0, &readfds, &writefds, NULL, &tv); if (!Active) break; // // 既存セッションとの送受信 // SessionListLock.Lock(); ssit = sss.begin(); SessionListLock.Unlock(); while (Active) { bool end = false; SessionListLock.Lock(); { if (ssit == sss.end()) end = true; } SessionListLock.Unlock(); if (end) break; O2SocketSession *ss = *ssit; // IP文字列 wstring ipstr; if (O2DEBUG) ulong2ipstr(ss->ip, ipstr); else ip2e(ss->ip, ipstr); // Send if (FD_ISSET(ss->sock, &writefds)) { int len; const char *buff = ss->GetNextSend(len); if (len > 0) { int n = send(ss->sock, buff, len, 0); if (n > 0) { ss->UpdateSend(n); ss->UpdateTimer(); SendByte += n; OnSend(ss); if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0); } } else if (n == 0) { ; } else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"送信エラー(%d)", lasterror); } ss->error = true; ss->Deactivate(); } } } // Recv if (FD_ISSET(ss->sock, &readfds)) { char buff[RECVBUFFSIZE]; int n = recv(ss->sock, buff, RECVBUFFSIZE, 0); if (n > 0) { ss->AppendRecv(buff, n); ss->UpdateTimer(); RecvByte += n; OnRecv(ss); if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 0, 0); } } else if (n == 0) { /*if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"受信0"); }*/ ss->Deactivate(); } else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"受信エラー(%d)", lasterror); } ss->error = true; ss->Deactivate(); } } // Delete if (ss->CanDelete()) { bool timeout = ss->GetPastTime() >= ss->timeout_s ? true : false; if (!ss->IsActive() || timeout) { if (timeout) { if (Logger) { Logger->AddLog(O2LT_NETERR, ClientName.c_str(), ss->ip, ss->port, L"timeout"); } } closesocket(ss->sock); ss->sock = 0; SessionListLock.Lock(); ssit = sss.erase(ssit); SessionListLock.Unlock(); OnClose(ss); continue; } } Sleep(1); SessionListLock.Lock(); ssit++; SessionListLock.Unlock(); } } // End SessionListLock.Lock(); for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; closesocket(ss->sock); ss->sock = 0; OnClose(ss); } sss.clear(); SessionListLock.Unlock(); }