删除空闲套接字
Removing an idle socket
在 C# 异步套接字服务器中 - 我需要识别空闲连接并将其删除。我怎么做?我的客户端有一个我在 DataHoldingUserToken 中设置的唯一 ID - 同一个客户端可能会删除以前的连接并创建一个新连接。那时我想到达为前一个连接提供服务的套接字并将该套接字和 return 处理到池中。我该如何实现?
我的代码在这里
class DataHoldingUserToken
{
internal Mediator theMediator;
internal DataHolder theDataHolder;
// internal dataProcessorAtrack AtrackProcessorHere;
internal Int32 socketHandleNumber;
internal readonly Int32 bufferOffsetReceive;
internal readonly Int32 permanentReceiveMessageOffset;
internal readonly Int32 bufferOffsetSend;
public bool needToSendbackKP;
public bool needToSendBackACK;
public bool sendBackSameSignal;
public int flagUnitType = -1;
public Int64 unitID = -1;
public Int32 seqIDINT = -1;
public byte[] ACKToSend;
private Int32 idOfThisObject; //for testing only
private object lockerForTokenList = new object();
internal Int32 lengthOfCurrentIncomingMessage;
//receiveMessageOffset is used to mark the byte position where the message
//begins in the receive buffer. This value can sometimes be out of
//bounds for the data stream just received. But, if it is out of bounds, the
//code will not access it.
internal Int32 receiveMessageOffset;
internal Byte[] byteArrayForPrefix;
internal readonly Int32 receivePrefixLength;
internal Int32 receivedPrefixBytesDoneCount = 0;
internal Int32 receivedMessageBytesDoneCount = 0;
//This variable will be needed to calculate the value of the
//receiveMessageOffset variable in one situation. Notice that the
//name is similar but the usage is different from the variable
//receiveSendToken.receivePrefixBytesDone.
internal Int32 recPrefixBytesDoneThisOp = 0;
internal Int32 sendBytesRemainingCount;
internal readonly Int32 sendPrefixLength;
internal Byte[] dataToSend;
internal Int32 bytesSentAlreadyCount;
//The session ID correlates with all the data sent in a connected session.
//It is different from the transmission ID in the DataHolder, which relates
//to one TCP message. A connected session could have many messages, if you
//set up your app to allow it.
private Int32 sessionId;
public DataHoldingUserToken(SocketAsyncEventArgs e, Int32 rOffset, Int32 sOffset, Int32 receivePrefixLength, Int32 sendPrefixLength, Int32 identifier)
{
this.idOfThisObject = identifier;
//Create a Mediator that has a reference to the SAEA object.
this.theMediator = new Mediator(e);
this.bufferOffsetReceive = rOffset;
this.bufferOffsetSend = sOffset;
this.receivePrefixLength = receivePrefixLength;
this.sendPrefixLength = sendPrefixLength;
this.receiveMessageOffset = rOffset + receivePrefixLength;
this.permanentReceiveMessageOffset = this.receiveMessageOffset;
this.needToSendbackKP = false;
this.needToSendBackACK = false;
// this.AtrackProcessorHere = new dataProcessorAtrack();
}
//Let's use an ID for this object during testing, just so we can see what
//is happening better if we want to.
public Int32 TokenId
{
get
{
return this.idOfThisObject;
}
}
internal void CreateNewDataHolder()
{
theDataHolder = new DataHolder();
}
//Used to create sessionId variable in DataHoldingUserToken.
//Called in ProcessAccept().
internal void CreateSessionId()
{
sessionId = Interlocked.Increment(ref Program.mainSessionId);
}
public Int32 SessionId
{
get
{
return this.sessionId;
}
}
public void Reset()
{
this.receivedPrefixBytesDoneCount = 0;
this.receivedMessageBytesDoneCount = 0;
this.recPrefixBytesDoneThisOp = 0;
this.receiveMessageOffset = this.permanentReceiveMessageOffset;
// this.needToSendBackACK = false;
// this.needToSendbackKP = false;
}
}
}
//AddTokenToList 正在消息处理程序内部为新连接上的第一个传入数据触发
bool incomingTcpMessageIsReady = messageHandler.HandleMessage(receiveSendEventArgs, receiveSendToken, remainingBytesToProcess);
if (incomingTcpMessageIsReady == true)
{
...
AddTokenToList(receiveSendToken);
}
private void AddTokenToList(DataHoldingUserToken theUserToken)
{
lock (this.lockerForList)
{
DataHoldingUserToken uTokenHere;
for (int countT = 0; countT < Program.listOfTokens.Count; countT++)
{
uTokenHere = (DataHoldingUserToken) Program.listOfTokens[countT];
if (uTokenHere.unitID == theUserToken.unitID)
{
//remove the previous socket
}
else {
Program.listOfTokens.Add(theUserToken);
}
}
}
}
TCP 是面向连接的。当您的对等端优雅地关闭连接时,这意味着客户端不会崩溃或拔出插头,他将关闭套接字。服务器通过在他的 0 字节套接字端接收到一个接收来检测到这个关闭。得到这个意味着是时候关闭你的套接字端了。
使用 TCP 时,如果没有消息交换正在进行,则无法检测到 TCP 连接已断开。检测连接断开的唯一方法是使用 keep alive,或者在每个时间间隔从服务器向客户端发送一条简单消息,从而有效地实现自己的 keep alive。如果客户端在几次重传后没有响应,您可以关闭您的连接。
在 C# 异步套接字服务器中 - 我需要识别空闲连接并将其删除。我怎么做?我的客户端有一个我在 DataHoldingUserToken 中设置的唯一 ID - 同一个客户端可能会删除以前的连接并创建一个新连接。那时我想到达为前一个连接提供服务的套接字并将该套接字和 return 处理到池中。我该如何实现?
我的代码在这里
class DataHoldingUserToken
{
internal Mediator theMediator;
internal DataHolder theDataHolder;
// internal dataProcessorAtrack AtrackProcessorHere;
internal Int32 socketHandleNumber;
internal readonly Int32 bufferOffsetReceive;
internal readonly Int32 permanentReceiveMessageOffset;
internal readonly Int32 bufferOffsetSend;
public bool needToSendbackKP;
public bool needToSendBackACK;
public bool sendBackSameSignal;
public int flagUnitType = -1;
public Int64 unitID = -1;
public Int32 seqIDINT = -1;
public byte[] ACKToSend;
private Int32 idOfThisObject; //for testing only
private object lockerForTokenList = new object();
internal Int32 lengthOfCurrentIncomingMessage;
//receiveMessageOffset is used to mark the byte position where the message
//begins in the receive buffer. This value can sometimes be out of
//bounds for the data stream just received. But, if it is out of bounds, the
//code will not access it.
internal Int32 receiveMessageOffset;
internal Byte[] byteArrayForPrefix;
internal readonly Int32 receivePrefixLength;
internal Int32 receivedPrefixBytesDoneCount = 0;
internal Int32 receivedMessageBytesDoneCount = 0;
//This variable will be needed to calculate the value of the
//receiveMessageOffset variable in one situation. Notice that the
//name is similar but the usage is different from the variable
//receiveSendToken.receivePrefixBytesDone.
internal Int32 recPrefixBytesDoneThisOp = 0;
internal Int32 sendBytesRemainingCount;
internal readonly Int32 sendPrefixLength;
internal Byte[] dataToSend;
internal Int32 bytesSentAlreadyCount;
//The session ID correlates with all the data sent in a connected session.
//It is different from the transmission ID in the DataHolder, which relates
//to one TCP message. A connected session could have many messages, if you
//set up your app to allow it.
private Int32 sessionId;
public DataHoldingUserToken(SocketAsyncEventArgs e, Int32 rOffset, Int32 sOffset, Int32 receivePrefixLength, Int32 sendPrefixLength, Int32 identifier)
{
this.idOfThisObject = identifier;
//Create a Mediator that has a reference to the SAEA object.
this.theMediator = new Mediator(e);
this.bufferOffsetReceive = rOffset;
this.bufferOffsetSend = sOffset;
this.receivePrefixLength = receivePrefixLength;
this.sendPrefixLength = sendPrefixLength;
this.receiveMessageOffset = rOffset + receivePrefixLength;
this.permanentReceiveMessageOffset = this.receiveMessageOffset;
this.needToSendbackKP = false;
this.needToSendBackACK = false;
// this.AtrackProcessorHere = new dataProcessorAtrack();
}
//Let's use an ID for this object during testing, just so we can see what
//is happening better if we want to.
public Int32 TokenId
{
get
{
return this.idOfThisObject;
}
}
internal void CreateNewDataHolder()
{
theDataHolder = new DataHolder();
}
//Used to create sessionId variable in DataHoldingUserToken.
//Called in ProcessAccept().
internal void CreateSessionId()
{
sessionId = Interlocked.Increment(ref Program.mainSessionId);
}
public Int32 SessionId
{
get
{
return this.sessionId;
}
}
public void Reset()
{
this.receivedPrefixBytesDoneCount = 0;
this.receivedMessageBytesDoneCount = 0;
this.recPrefixBytesDoneThisOp = 0;
this.receiveMessageOffset = this.permanentReceiveMessageOffset;
// this.needToSendBackACK = false;
// this.needToSendbackKP = false;
}
}
}
//AddTokenToList 正在消息处理程序内部为新连接上的第一个传入数据触发
bool incomingTcpMessageIsReady = messageHandler.HandleMessage(receiveSendEventArgs, receiveSendToken, remainingBytesToProcess);
if (incomingTcpMessageIsReady == true)
{
...
AddTokenToList(receiveSendToken);
}
private void AddTokenToList(DataHoldingUserToken theUserToken)
{
lock (this.lockerForList)
{
DataHoldingUserToken uTokenHere;
for (int countT = 0; countT < Program.listOfTokens.Count; countT++)
{
uTokenHere = (DataHoldingUserToken) Program.listOfTokens[countT];
if (uTokenHere.unitID == theUserToken.unitID)
{
//remove the previous socket
}
else {
Program.listOfTokens.Add(theUserToken);
}
}
}
}
TCP 是面向连接的。当您的对等端优雅地关闭连接时,这意味着客户端不会崩溃或拔出插头,他将关闭套接字。服务器通过在他的 0 字节套接字端接收到一个接收来检测到这个关闭。得到这个意味着是时候关闭你的套接字端了。
使用 TCP 时,如果没有消息交换正在进行,则无法检测到 TCP 连接已断开。检测连接断开的唯一方法是使用 keep alive,或者在每个时间间隔从服务器向客户端发送一条简单消息,从而有效地实现自己的 keep alive。如果客户端在几次重传后没有响应,您可以关闭您的连接。