Пример #1
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) 
						{
#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();
				}
			}
Пример #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();
}