Пример #1
0
uint
O2Agent::
NetIOThread(void)
{
	O2SocketSessionListIt ssit;
	int lasterror;

	while (Active) {
		//setup FD
		fd_set readfds;
		fd_set writefds;
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);

		//wait
		Lock();
		uint n = sss.size();
		Unlock();
		if (n == 0) {
			ResetEvent(SessionAvailableEvent);
		}
		WaitForSingleObject(SessionAvailableEvent, INFINITE);
		if (!Active)
			break;

		//FD
		Lock();
		for (ssit = sss.begin(); ssit != sss.end(); ssit++) {
			O2SocketSession *ss = *ssit;
			if (!ss->sendcomplete)
				FD_SET(ss->sock, &writefds);
			else
				FD_SET(ss->sock, &readfds);
		}
		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);

		//
		//	既存セッションとの送受信
		//
		Lock();
		ssit = sss.begin();
		Unlock();
		while (1) {
			bool loopend = false;
			Lock();
			if (ssit == sss.end())
				loopend = true;
			Unlock();
			if (loopend)
				break;

#if DEBUG_THREADLOOP && defined(_DEBUG)
			TRACEA("[NetIO]\n");
#endif
			O2SocketSession *ss = *ssit;
			O2AgentService *service = (O2AgentService*)ss->service;

			ushort port = htons(ss->sin.sin_port);
			wstring ipstr;
#if defined (_DEBUG)
			ulong2ipstr(ss->sin.sin_addr.S_un.S_addr, ipstr);
#else
			ip2e(ss->sin.sin_addr.S_un.S_addr, ipstr);
#endif
			//send
			if (FD_ISSET(ss->sock, &writefds)) {
				int len;
				const char *buff = ss->GetSendBuffer(len);
				if (len > 0) {
					int n = send(ss->sock, buff, len, 0);
#if DEBUG_THREADLOOP && defined(_DEBUG)
					TRACEA("[A]send\n");
#endif
					if (n > 0) {
						ss->UpdateSend(n);
						NodeDB->IncrementSendByte_me2n(ss->sin.sin_addr.S_un.S_addr, n);
						service->IncrementSendByte(n);
						service->OnSend(ss);
						ss->UpdateTimer();

						if (hwndSetIconCallback) {
							PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0);
						}
					}
					else if (n == 0) {
						;
					}
					else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) {
						if (Logger) {
							Logger->AddLog(O2LT_NET, MODULE,
								L"送信エラー(%d) (%s %s:%d %dbyte)",
								lasterror, service->GetName(), ipstr.c_str(), port, ss->sbuff.size());
						}
						ss->SetActive(false);
					}
				}
			}

			//recv
			if (FD_ISSET(ss->sock, &readfds)) {
				char buff[RECVBUFFSIZE];
				int n = recv(ss->sock, buff, RECVBUFFSIZE, 0);
#if DEBUG_THREADLOOP && defined(_DEBUG)
				TRACEA("[A]recv\n");
#endif
				if (n > 0) {
					ss->AppendRecv(buff, n);
					NodeDB->IncrementRecvByte_me2n(ss->sin.sin_addr.S_un.S_addr, n);
					service->IncrementRecvByte(n);
					service->OnRecv(ss);
					ss->UpdateTimer();

					if (hwndSetIconCallback) {
						PostMessage(hwndSetIconCallback, msgSetIconCallback, 0, 0);
					}
				}
				else if (n == 0) {
					if (Logger) {
						Logger->AddLog(O2LT_NET, MODULE,
							L"受信0 (%s %s:%d)",
								service->GetName(), ipstr.c_str(), port);
					}
					ss->SetActive(false);

				}
				else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) {
					if (Logger) {
						Logger->AddLog(O2LT_NET, MODULE,
						L"受信エラー(%d) (%s %s:%d %dbyte)",
						lasterror, service->GetName(), ipstr.c_str(), port, ss->rbuff.size());
					}
					ss->SetActive(false);
				}
			}

			//delete
			if (!ss->IsActive() || ss->GetPastTime() >= SOCKET_TIMEOUT_S) {
				void *databk = ss->data;
				ulong ip = ss->sin.sin_addr.S_un.S_addr;
				closesocket(ss->sock);
				service->OnClose(ss);
				NodeDB->RemoveStatusBit(ip, O2_NODESTATUS_LINKEDTO);
				NodeDB->AddStatusBit(ip, O2_NODESTATUS_PASTLINKEDTO);
				service->DecrementCount();

				if (!ss->rbuff.empty() && !ss->sbuff.empty()) {
					NodeDB->UpdateLastModified(ip, 2);
					service->IncrementTotalSessionCount();
				}
				else if (ss->rbuff.empty())
					NodeDB->IncrementErrorCount(ip, 1);
				if (!ss->rbuff.empty() && (!databk || ss->rbuff[0] != 'H')) {
					NodeDB->DeleteNode(ip);

					if (Logger) {
						Logger->AddLog(O2LT_WARNING, MODULE,
							L"不正データ受信 (ノード削除: %s:%d)",
							ipstr.c_str(), htons(ss->sin.sin_port));
					}

					if (O2DEBUG) {
						char filename[256];
						sprintf_s(filename, 256, "dump\\A_%d.txt", rand());
						FILE *fp;
						fopen_s(&fp, filename, "wb");
						fwrite(ss->rbuff.c_str(), ss->rbuff.size(), 1, fp);
						fclose(fp);
					}
				}
#if DEBUG_SESSION_COUNT && defined(_DEBUG)
				wchar_t abc[256]; swprintf(abc, L"■■削除■■ count:%d  limit:%d  %s\n",
					service->GetSessionCount(), service->GetSessionLimit(), service->GetName());
				TRACEW(abc);
#endif
				Lock();
				ssit = sss.erase(ssit);
				Unlock();
				delete ss;
				continue;
			}

			Sleep(1);
			ssit++;
		}
	}

	//end
	Lock();
	for (ssit = sss.begin(); ssit != sss.end(); ssit++) {
		O2SocketSession *ss = *ssit;
		closesocket(ss->sock);
		ss->sock = 0;
		((O2AgentService*)((O2AgentService*)ss->service))->OnClose(ss);
		delete ss;
	}
	sss.clear();
	Unlock();

	return (0);
}
Пример #2
0
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();
}