개발관련/C#

소켓 비정상 종료 처리 TcpKeepAlive

Diademata 2018. 9. 13. 00:25
반응형

비정상 종료로 인하여 고스트 세션이 발생하였을 때 처리 방법으론 자체적으로 HeartBeat를 만들어 주기적으로 Send를 하거나


소켓 옵션을 통하여 처리하면 된다.


window 서버 2010 이상, Window 8.1 이상 지원


C# => IOControl


WinSock => WSAIoctl을 사용하면 된다.


소켓을 IOCP에 물렸을 경우 GetQueuedCompletionStatus()에서 False와 ERROR_SEM_TIMEOUT Error로 떨어짐.


C#


public class TcpKeepAlive

{

public uint OnOff { get; set; }

public uint KeepAliveTime { get; set; }

public uint KeepAliveInterval { get; set; }

public byte[] GetBytes()

{

return BitConverter.GetBytes(OnOff).Concat(BitConverter.GetBytes(KeepAliveTime)).Concat(BitConverter.GetBytes(KeepAliveInterval)).ToArray();

}

}


var option = new TcpKeepAlive

{

OnOff = 1,

KeepAliveTime = 5000,

KeepAliveInterval = 1000

};

state.Socket.IOControl(IOControlCode.KeepAliveValues, option.GetBytes(), null);


C++ 

#include <mstcpip.h>


tcp_keepalive keepAlive;

keepAlive.onoff = 1;

keepAlive.keepalivetime = 5000;

keepAlive.keepaliveinterval = 1000;

DWORD option;


WSAIoctl(stateObject->Socket(), SIO_KEEPALIVE_VALS, &keepAlive, sizeof(keepAlive), 0, 0, &option, NULL, NULL);


if (!GetQueuedCompletionStatus(_completionPort, &bytesTrans, &stateObject, (LPOVERLAPPED *)&overlapped, INFINITE))

{

int error = WSAGetLastError();

printf("Error : %d\n", error);

auto pHandler = reinterpret_cast<StateObject*>(stateObject);

switch (error)

{

case ERROR_SEM_TIMEOUT:

case ERROR_NETNAME_DELETED:

ClosePeer(pHandler);

default:

break;

}

 continue;


}

반응형