ソケットプログラミングを含むアプリケーションに取り組んでいます。サーバーが何らかの理由で閉じられたりクラッシュした場合に備えて、このアプリケーションにリセット機能を実装しようとしています。リセットするには、サーバーを手動で再起動した後、クライアントとサーバー間の通信を再確立する必要があります。これで、クライアントからサーバーに要求を送信し、サーバーが処理してクライアントに応答を送信できるようになりました。Send()
サーバー側の関数は成功して返されますがWSAWaitForMultipleEvents()
、クライアント側の関数はWSA_TIME_OUT
毎回返されます。
SO_REUSEADDR
リセット時に真の値でクライアント側でソケットを再起動します。私はネットワークプログラミングに非常に慣れていないので、なぜこれが起こっているのか理解できません。
これがクライアント側の私のコードです。少しめちゃくちゃなので、ご容赦ください
void
SocketListner::run()
{
// std::cout << "Thread ID of SocketListener : " << QThread::currentThreadId() << "\n";
if(_isFrameGrabber)
{
_listenForFrames();
}
else
{
_listenForRequests();
}
}
void
SocketListner::_listenForRequests()
{
DWORD eventVal;
unsigned int eventSock;
WSANETWORKEVENTS networkEvents;
std::stringstream ss;
int bufferLength = 500;
char * msg = new char[bufferLength];
std::string Msg = "";
int retCode;
int diff;
while(!_done)
{
// Giving it one second less than the condition wait time
// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_destructorMutex);
if((eventVal=WSAWaitForMultipleEvents(_eventCnt, _socketEvents, false, 3000, false)) == WSA_WAIT_FAILED)
{
ss.str("");
ss << "WSAWaitForMultipleEvents() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
emit socketErrorSignal(eventVal);
break;
}
else if(eventVal == WSA_WAIT_TIMEOUT)
{
//OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
if(_done)
{
WSACloseEvent(_socketEvents[0]);
if(_eventCnt==2)
WSACloseEvent(_socketEvents[1]);
break;
}
continue;
}
if( (diff=(eventVal - WSA_WAIT_EVENT_0)) == 0 )
eventSock = s_sock;
else if(diff == 1)
eventSock = c_sock;
else
continue;
if((WSAEnumNetworkEvents(eventSock, _socketEvents[eventVal - WSA_WAIT_EVENT_0], &networkEvents)) == SOCKET_ERROR)
{
ss.str("");
ss << "WSAEnumNetworkEvents() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
// break;
}
if (networkEvents.lNetworkEvents & FD_ACCEPT)
{
if (networkEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
{
ss.str("");
ss << "FD_ACCEPT failed with error : " << networkEvents.iErrorCode[FD_ACCEPT_BIT];
LOG_ERROR(ss.str());
break;
}
if ((c_sock = accept(eventSock, NULL, NULL)) == INVALID_SOCKET)
{
ss.str("");
ss << "accept() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
break;
}
if ((_socketEvents[_eventCnt] = WSACreateEvent()) == WSA_INVALID_EVENT)
{
std::stringstream ss;
ss << "WSACreateEvent() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
break;
}
if( WSAEventSelect(c_sock, _socketEvents[_eventCnt], FD_READ | FD_CLOSE) == SOCKET_ERROR)
{
ss.str("");
ss << "WSAEventSelect() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
break;
}
++_eventCnt;
}
if(networkEvents.lNetworkEvents & FD_READ)
{
if (networkEvents.lNetworkEvents & FD_READ && networkEvents.iErrorCode[FD_READ_BIT] != 0)
{
ss.str("");
ss << "FD_READ failed with error : " << networkEvents.iErrorCode[FD_READ_BIT];
LOG_ERROR(ss.str());
}
if((retCode = recv(eventSock, msg, bufferLength, 0)) > 0)
{
int place = 0;
while(place < retCode)
{
if(msg[place] == '\n' && Msg.length() != 0)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
//Naresh: Replacing std::vector by std::queue
_requests.push(Msg);
Msg = "";
}
else
{
if(msg[place] != '\0')
Msg.push_back(msg[place]);
}
++place;
}
}
//Abhishek: Testing Complete else block
else if(retCode == 0 || WSAGetLastError() == WSAECONNRESET)
{
//Abhishek
shutdown(c_sock, SD_BOTH);
shutdown(s_sock, SD_BOTH);
closesocket(c_sock);
closesocket(s_sock);
int error = WSAGetLastError();
if(!_initialize())
{
_done = true;
return;
}
}
else if(retCode == SOCKET_ERROR)
{
bool stopListening=false;
int errorCode = WSAGetLastError();
_processSocketError(errorCode, stopListening);
if(stopListening)
{
LOG_WARNING("Connection with the partner lost.");
emit socketErrorSignal(errorCode);
break;
}
}
}
if(networkEvents.lNetworkEvents & FD_CLOSE)
{
if (networkEvents.iErrorCode[FD_CLOSE_BIT] != 0)
{
ss.str("");
ss << "FD_CLOSE failed with error : " << networkEvents.iErrorCode[FD_CLOSE_BIT];
LOG_ERROR(ss.str());
emit socketErrorSignal(networkEvents.iErrorCode[FD_CLOSE_BIT]);
}
else if(!_stopped)
{
LOG_ERROR("Lost Connection with Wall.");
emit socketErrorSignal(networkEvents.iErrorCode[FD_CLOSE_BIT]);
}
closesocket(eventSock);
break;
}
//Sleep(100);
} //While
delete[] msg;
msg = NULL;
// If any failure occurs make the _bDone variable to true, as thread is no longer running
_cleanUpCondition.signal();
}
ここに_initialize関数があります
bool
SocketListner::_initialize()
{
if(_IP.length() <= 0)
{
LOG_ERROR("Host IP Address : " + _IP + " is invalid.");
return false;
}
//Naresh: replacing vector by queue
while(!_requests.empty())
{
_requests.pop();
}
WSADATA wsaData;
if(WSAStartup(0x101,&wsaData) != 0)
{
LOG_ERROR("Failed WSAStartUp() call.");
return false;
}
sockaddr_in SockAddr;
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons(_port);
SockAddr.sin_addr.s_addr = inet_addr(_IP.c_str());
s_sock = socket(AF_INET,SOCK_STREAM,0);
//Abhishek:BugFix for reset enable address reuse else bind() will fail
bool addrReuse = true;
setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, (const char*) &addrReuse, sizeof(BOOL));
if(!_isFrameGrabber)
{
if ((_socketEvents[_eventCnt] = WSACreateEvent()) == WSA_INVALID_EVENT)
{
std::stringstream ss;
ss << "WSACreateEvent() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
return false;
}
if(WSAEventSelect(s_sock, _socketEvents[_eventCnt], FD_ACCEPT | FD_CLOSE)== SOCKET_ERROR)
{
std::stringstream ss;
ss << "WSAEventSelect() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
return false;
}
++_eventCnt;
}
if(s_sock == INVALID_SOCKET)
return false;
int errorCode = bind(s_sock,(sockaddr*)&SockAddr,sizeof(SockAddr));
if(errorCode == SOCKET_ERROR)
{
bool stopListening = false;
_processSocketError(WSAGetLastError(), stopListening);
return false;
}
if(listen(s_sock,10)!=0)
{
return false;
}
return true;
}