我编写了一个应该管理许多客户端的服务器端应用程序。一切都是使用BeginSend()和EndSend()方法异步完成的。
在某些情况下,我需要向其中一个客户端发送两个后续请求。我希望确保在第一个 BeginSend()和 last EndSend()之间没有调用新的BeginSend()。我虽然使用AutomaticResetEvent执行此操作,但如果服务器尝试向客户端发送两条消息,则第二条消息将阻塞,直到第一条消息被发送
感谢您的见解。
struct SendBuffer
{
public const int BUFFER_SIZE = 1024 * 128;
public byte[] BUFFER;
public int sent;
public SendBuffer(byte[] data)
{
BUFFER = new byte[data.Length];
Buffer.BlockCopy(data, 0, BUFFER, 0, data.Length);
sent = 0;
}
public void Dispose()
{
BUFFER = null;
sent = 0;
}
}
public void SendAsyncData(string str, CommandsToClient cmd)
{
byte[] data = Combine(BitConverter.GetBytes((int)(cmd)), BitConverter.GetBytes((int)(str.Length)), Encoding.ASCII.GetBytes(str));
SendAutoResetEvent.WaitOne();
SendAsyncDataWithHeader(data);
}
private void SendAsyncDataWithHeader(byte[] data)
{
int toSend;
byte[] dataWithHeader = Combine(BitConverter.GetBytes(data.Length), data);
sendBuffer = new SendBuffer(dataWithHeader);
if (sendBuffer.BUFFER.Length - sendBuffer.sent > SendBuffer.BUFFER_SIZE)
toSend = SendBuffer.BUFFER_SIZE;
else
toSend = sendBuffer.BUFFER.Length - sendBuffer.sent;
try
{
socket.BeginSend(sendBuffer.BUFFER, 0, toSend, SocketFlags.None, sendCallback, null);
}
catch (SocketException se)
{
switch (se.SocketErrorCode)
{
case SocketError.ConnectionAborted:
case SocketError.ConnectionReset:
if (Disconnected != null)
{
Disconnected(this);
}
break;
}
}
catch (ObjectDisposedException)
{
}
catch (NullReferenceException ex)
{
}
catch (Exception ex)
{
Disconnected(this);
}
}
void sendCallback(IAsyncResult ar)
{
try
{
int bytesSent = socket.EndSend(ar);
if (bytesSent == 0)
{
if (Disconnected != null)
{
Disconnected(this);
return;
}
}
sendBuffer.sent += bytesSent;
if (sendBuffer.sent == sendBuffer.BUFFER.Length)
{
//all data was sent. do some
//do some processing...
sendBuffer.Dispose();
//let new send request in
SendAutoResetEvent.Set();
return;
}
int toSend;
// exception says that in the following line, sendBuffer.Buffer is null....
if (sendBuffer.BUFFER.Length - sendBuffer.sent > SendBuffer.BUFFER_SIZE)
toSend = SendBuffer.BUFFER_SIZE;
else
toSend = sendBuffer.BUFFER.Length - sendBuffer.sent;
socket.BeginSend(sendBuffer.BUFFER, sendBuffer.sent, toSend, SocketFlags.None, sendCallback, null);
}
catch (SocketException se)
{
switch (se.SocketErrorCode)
{
case SocketError.ConnectionAborted:
case SocketError.ConnectionReset:
if (Disconnected != null)
{
Disconnected(this);
return;
}
break;
}
}
catch (ObjectDisposedException ex)
{
}
catch (NullReferenceException ex)
{
//here an exception is thrown,
}
catch (Exception ex)
{
Disconnected(this);
}
}
}
}