我无法关闭空闲的TCP套接字。我的客户端经常重新连接并从SocketAsynchEventArgs对象池创建一个新套接字。我将所有套接字存储在列表中,并将当前工作套接字存储在哈希表中,但无法关闭现在空闲的套接字。我也在usertoken中存储活动的最后一次。我的计时器每2分钟开火一次。如果活动的最后一次超过6分钟,我希望关闭该套接字并将其返回到池中。贴在下面是我的功能。当空闲时间超过6分钟时,需要以某种方式调用CloseClientSocket函数。有时(不是通过计时器)我可以看到这个代码执行SocketError.TimedOut。接收超时和发送超时设置为60秒进行测试。当发生这种情况时,套接字被释放,一切都很好。所以我需要这个函数从下面粘贴的层函数FireThistimer触发。请帮忙。让我补充一点,如果我从计时器函数调用CloseClientSocket,TCP服务器就会完全停止。
private void CloseClientSocket(SocketAsyncEventArgs e)
{
try
{
var receiveSendToken = (e.UserToken as DataHoldingUserToken);
{
Program.testWriter.WriteLine("CloseClientSocket, id " + receiveSendToken.TokenId);
}
if (Program.watchThreads == true) //for testing
{
DealWithThreadsForTesting("CloseClientSocket()", receiveSendToken);
}
// do a shutdown before you close the socket
try
{
if (Program.watchProgramFlow == true) //for testing
{
Program.testWriter.WriteLine("CloseClientSocket, Shutdown try, id " + receiveSendToken.TokenId + "\r\n");
}
removeEntryInHashTableBySocket(e);
receiveSendToken.unitID = -1;
receiveSendToken.flagUnitType = -1;
receiveSendToken.seqIDINT = -1;
receiveSendToken.needToSendbackKP = false;
receiveSendToken.needToSendBackACK = false;
// receiveSendToken.ACKToSend = null;
Thread.Sleep(500);
e.AcceptSocket.Shutdown(SocketShutdown.Both);
} // throws if socket was already closed
catch (Exception xCS)
{
Console.WriteLine("Socket is already closed " + xCS.Message);
if (Program.watchProgramFlow == true) //for testing
{
Program.testWriter.WriteLine("CloseClientSocket, Shutdown catch, id " + receiveSendToken.TokenId + "\r\n");
}
}
//This method closes the socket and releases all resources, both
//managed and unmanaged. It internally calls Dispose.
try
{
if (e != null)
{
e.AcceptSocket.Close();
//here to remove from listOfSockets
if(Program.listOfSockets.Contains(e))
{
RemoveFromListOfSocket(e);
}
}
}
catch (Exception)
{
Console.WriteLine("ERROR in Client Close ..");
}
//Make sure the new DataHolder has been created for the next connection.
//If it has, then dataMessageReceived should be null.
if (receiveSendToken.theDataHolder.dataMessageReceived != null)
{
receiveSendToken.CreateNewDataHolder();
}
// Put the SocketAsyncEventArg back into the pool,
// to be used by another client. This
this.poolOfRecSendEventArgs.Push(e);
// decrement the counter keeping track of the total number of clients
//connected to the server, for testing
Interlocked.Decrement(ref this.numberOfAcceptedSockets);
if (Program.watchConnectAndDisconnect == true) //for testing
{
Program.testWriter.WriteLine(receiveSendToken.TokenId + " disconnected. " + this.numberOfAcceptedSockets + " client(s) connected.");
}
//Release Semaphore so that its connection counter will be decremented.
//This must be done AFTER putting the SocketAsyncEventArg back into the pool,
//or you can run into problems.
this.theMaxConnectionsEnforcer.Release();
}
catch (Exception What1)
{
Console.WriteLine(What1.Message);
}
}
private void FireThisTimer(object source, ElapsedEventArgs e)
{
try
{
DataHoldingUserToken theUserTokenHere;
Int64 unitInKey;
int listcount4 = Program.listOfSockets.Count;
Console.WriteLine("Timer fired with sockets = " + listcount4.ToString());
SocketAsyncEventArgs[] array4Purge = new SocketAsyncEventArgs[listcount4];
Program.listOfSockets.CopyTo(array4Purge);
foreach (SocketAsyncEventArgs socket4 in array4Purge)
{
try
{
theUserTokenHere = (DataHoldingUserToken)socket4.UserToken;
unitInKey = theUserTokenHere.unitID;
double timeSincePrevData = calcTimeInterval(theUserTokenHere);
if (timeSincePrevData > 6)
{
Console.WriteLine("Found idle socket with unitid =" + unitInKey);
socket4.SocketError = SocketError.TimedOut;
socket4.AcceptSocket.Shutdown(SocketShutdown.Both);
theUserTokenHere.Reset();
}
}
catch (Exception xVB)
{
Console.WriteLine("Continuing after exception in for loop "+xVB.Message);
continue;
}
}
Console.WriteLine("Sockets at the end of timer event = " + Program.listOfSockets.Count.ToString());
}
catch (Exception xCE)
{
Console.WriteLine("Timer Exception is " + xCE.Message);
}
}