2012-07-25 37 views
3

我最初在发送数据时有一个竞争条件,问题是我允许使用多个SocketAsyncEventArgs发送数据,但第一个数据包在第二个数据包之前没有完全发送,是因为我有它,所以如果数据不适合缓冲区,它会循环直到发送所有数据,并且第一个数据包比第二个数据包很小,所以第二个数据包被发送并到达客户端在第一个包之前。按照SocketAsyncEventArgs的顺序发送数据

我已经解决了这个问题,方法是将一个SocketAyncEventArgs分配给用于发送数据的打开连接,并使用信号量来限制对它的访问,并在完成后返回SocketAsyncEventArgs。

现在,这工作正常,因为所有的数据发送,回拨完成后准备下一次发送。与此相关的问题是,当我想随机发送数据到打开的连接时,以及当发送大量数据阻止我的线程时,它导致阻塞。

我正在寻找解决这个问题的方法,我想有一个队列,当请求发送数据时,它只是将数据包添加到队列中,然后1个SocketAsyncEventArgs只是循环发送该数据。

但是我怎样才能有效地做到这一点,同时仍然是可扩展的?我希望尽可能避免阻塞,同时按照请求发送的顺序发送我的数据包。

感谢任何帮助!

回答

4

如果数据需要按顺序保存,并且您不想阻塞,那么您需要添加一个队列。我这样做的方式是通过跟踪我的状态对象来确定我们是否已经为该连接处理了一个活动的发送异步循环。排队(这显然必须同步)之后,只是检查什么是正在进行:

public void PromptToSend(NetContext context) 
    { 
     if(Interlocked.CompareExchange(ref writerCount, 1, 0) == 0) 
     { // then **we** are the writer 
      context.Handler.StartSending(this); 
     } 
    } 

这里writerCount是写循环的次数(这应该是完全0或1)上的连接;如果没有,我们开始一个。我的StartSending试图从该连接的队列中读取;如果能做到这一点,它通常SendAsync等:

if (!connection.Socket.SendAsync(args)) SendCompleted(args); 

(注意SendCompleted这里是“同步”的情况下,它会通过事件,型号为“异步”情况已经得到了SendCompleted )。 SendCompleted显然重复此“出队,尝试发送异步”步骤。

剩下的唯一的事情是确保当我们尝试出队,我们注意到没有采取行动,如果我们发现无事可做:

 if (bufferedLength == 0) 
     { // nothing to do; report this worker as inactive 
      Interlocked.Exchange(ref writerCount, 0); 
      return 0; 
     } 

有意义吗?

+0

所以我会做一个队列,当某些东西被添加到队列中时,检查一下发送操作是否已经在进行中,如果不是,那么启动一个并且它一直循环直到队列为空?一旦发送队列中的队列变为空,则将写入计数更改为0,并在需要时重新启动发送进程? – Matty 2012-07-25 12:12:07

+0

@mattysouthall正好。请注意,“保持循环”有一个* async *循环,而不是一个常规循环('while')等等。所以基本上,每当你得到“完成”事件,并且你检查了它是OK等,然后启动下一个去。 – 2012-07-25 13:03:12

+0

全部完成,工作很棒!我的日志显示它正在按照我想要的方式行事,谢谢! – Matty 2012-07-25 15:20:56

相关问题