我在写服务器程序时遇到个问题,没想明白。
连接后。
使用SendAsync发送
使用ReceiveAsync接收
都会响应Completed的回调,这很正常。我的服务端程序有这样一个需求:
连接后,服务器常态应处于ReceiveAsync状态,因为这样可以捕捉到客户端关闭连接的动作。
但有时又想给客户端发送数据,使用SendAsync时,会出现“现在已经正在使用此 SocketAsyncEventArgs 实例进行异步套接字操作。”
这可能是因为在做ReceiveAsync操作时,客户端没有发数据,没有完成操作。直接SendAsync会因为ReceiveAsync的操作没有完成而产生异常。请问我该如何实现这种需求?
是否有方法撤销上次的ReceiveAsync操作?

解决方案 »

  1.   

    如果想捕捉到客户端关闭连接的动作 那就是用心跳包的形式 客户端每个一段时间想服务器请求一次
    证明自己在线 一旦一段时间内无请求 服务器就可以捕捉到  这样就不会出现你遇到的问题!不要太过于依赖.NET提供的方法,虽然说它已经被封装的很好了,但是有时候实际应用中根据不同的
    情况使用不同的解决方案 往往更佳!
      

  2.   


    谢谢您。您的方法我考虑过,也曾使用过,只是我觉得不是很理想,总有和客户端交互,还要判断超时,感觉效率不高。但即使这样也没什么。我没想明白的是,Socket是双工的,用ReceiveAsync等待接收时,如果对方没有发送数据。我就不能用SendAsync发送数据,这不变成半双工了吗?没想明白。
      

  3.   


    一个线程
    一个Sokcet s
    一个SocketAsyncEventArgs e
    在某个方法
    void DoWork()
    {
      s.ReceiveAsync(e);
      Sleep(10000);
      if(如果需要)
      {
           s.SendAsync(e);//这里会异常
      }
    }
      

  4.   

    难怪了 一个线程中同时调用eceiveAsync和SendAsync并且没有切换状态肯定回报错啊!你可以一个线程用来接收请求 一个线程用来发送请求!  或是在发送请求时切换状态(至于怎么切换 需要查查)
      

  5.   

    这跟线程有关吗?
    不管几个线程,针对的都是一个Socket啊
    假设连个线程 A BA中
    ReceiveAsync操作没完成
    B中
    SendAsync就能正常发送吗?
      

  6.   

    我用Timer做过类似的操作 是不行的
      

  7.   

    我觉得在调用SendAsync前 让ReceiveAsync=false   调用完后在恢复! 不知是否可行!
      

  8.   

    是啊 我想的也是在SendAsync之前取消ReceiveAsync的操作。
    不过好像没有这方面的方法。刚刚查了些资料,如果要双工,需要实现两个SocketAsyncEventArgs,一个SEND 一个REC我正在看http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813649.html你可以看看。
      

  9.   

    呵呵  我也想给你说说 你要重复使用套接字 要实现
    BufferManager:缓冲区SocketAsyncEventArgsPool:事件池{可重复使用的套接字对象}才行   点此详细
      

  10.   


    new一个新的SocketAsyncEventArgs 实例。怎么能共用前一个实例呢?!
      

  11.   

    只有在你读取一个数据,然后又迭代地异步读的时候,这时候才应该或可以共用参数中的SocketAsyncEventArgs 实例,因为它已经被用完了(如果不用就会被GC回收)。其实这个时候new一个新实例也完全可以。其它时间,每当开启异步操作,都应该new一个SocketAsyncEventArgs 新实例。
      

  12.   

    奇怪,我在“异步读”这三个字之前写上“开启一个”四个字,csdn告诉我说有非法词组,不让我回复。
    这四个字怎么反动了吗?!奇怪呀。
      

  13.   


    最近连JAVAEYE都关了 风口浪尖啊!  CSDN也是坐立不安啊!
      

  14.   


    sp老大,对于你这个回复我有意见提:你这个回答是对的没有错误,但据微软给出的例子和你这个是完全不同的,他不是用的时候再NEW一个实例,而是在服务器初始化的时候便实例所需的N个实例(SocketAsyncEventArgs池),这样在性能上才有质的提升。
      

  15.   

    想不到现在用SocketAsyncEventArgs这个类的人越来越多了,不知楼主做完后能否给个压力测试的具体数据来看看,谢了!
      

  16.   

    我觉得 是因为 非线程安全的原因
    有好像 在两个线程中 UI线程A和后台线程B
    你在B线程中 修改 A线程中的对象 比如 一个控件的属性
    CLR就会报错 说不允许在B中访问A的对象我想应该是一个道理