private void readCallBack(IAsyncResult ar)
        {
            i++;
            StateObject state = (StateObject)ar.AsyncState;
            Socket handle = state.workSocket;
            int read = handle.EndReceive(ar);
            if (read > 0)
            {
                string data = Encoding.ASCII.GetString(state.buffer, 0, read);
                state.sb.Append(data);
                handle.BeginReceive(state.buffer, 0, StateObject.buffSize, 0, new AsyncCallback(readCallBack), state);
            }
            else
            {
                if(state.sb.Length>0)
                {
                    state.sb.Append("  共接收了" + i.ToString() + "次");
                    MessageBox.Show(state.sb.ToString());
                }
                handle.Close();
            }
        }    public class StateObject
    {
        public Socket workSocket = null;
        public const int buffSize = 1024;
        public Byte[] buffer = new byte[buffSize];
        public StringBuilder sb = new StringBuilder();
    }//////////////////////////////////////////
以上是异步接收数据的方法
sendText("windows");
经设断点提示,已经收到数据,而且是完整的,
可是MessageBox.Show(state.sb.ToString());
就是弹不出来请问高手们,如何处理边界问题?

解决方案 »

  1.   

    用事件或委托来实现提示,在异步线程中,直接用MessageBox不大好!
      

  2.   

    handle.BeginReceive(state.buffer,   0,   StateObject.buffSize,   0,   new   AsyncCallback(readCallBack),   state); 
    -------------
    在这里你设置的长度为StateObject.buffSize即1024,在获取的时候,他除了会获到了你发送的消息外,还会加上一些无聊的信息"\0",无法正常显示消息也应该就是这个原因.
    有两种方式可以解决:
    第一,用socket对象去获取到结束节点数count = mySocket.EndReceive(ar);然后用这个长度去接收数据就没有问题了
    另一个,可以可以接收到再去掉其后面的"\0",那样也可以正常显示.eg:string result=content.TrimEnd('\0');
      

  3.   

    to BookSirSwordsMan直接MessageBox我只是想测试一下我没有即时关闭就是所谓的长连接了
    to symbol441收到数据后,没有发现\0谢谢二位,希望二位继续关注!
      

  4.   

    to   symbol441第一,用socket对象去获取到结束节点数count   =   mySocket.EndReceive(ar);然后用这个长度去接收数据就没有问题了可是我怎么得到发送端发的数据长度呢?如果可以得到那就可以解决了!
      

  5.   

    symbol441 
    小红帽 
    等 级:
     发表于:2008-01-17 17:30:163楼 得分:0 
    handle.BeginReceive(state.buffer,       0,       StateObject.buffSize,       0,       new       AsyncCallback(readCallBack),       state);   
    ------------- 
    在这里你设置的长度为StateObject.buffSize即1024,在获取的时候,他除了会获到了你发送的消息外,还会加上一些无聊的信息"\0",无法正常显示消息也应该就是这个原因. 
    有两种方式可以解决: 
    第一,用socket对象去获取到结束节点数count   =   mySocket.EndReceive(ar);然后用这个长度去接收数据就没有问题了 
    另一个,可以可以接收到再去掉其后面的"\0",那样也可以正常显示.eg:string   result=content.TrimEnd('\0');  
     
    ------------------------------------------------------------------------------------------------------
    根本不会出现小红帽所说的现象,因为LZ已经用了这个
    string   data   =   Encoding.ASCII.GetString(state.buffer,   0,   read); 
    即读取有效的数据长度我总觉得是导步导致的问题,以致于MessageBox无效
    还有连接没有关闭int   read   =   handle.EndReceive(ar); 这句读取到的永远都是不为0的数据长度,只有在客户端进行关闭后,read才会为0也就是说连接没有关闭的情况下if(read > 0)是永远为真的情况,也就不可能执行到MessageBox了
      

  6.   

    ismycxp 
    风速 
    等 级:
     发表于:2008-01-17 18:25:545楼 得分:0 
    to       symbol441 第一,用socket对象去获取到结束节点数count       =       mySocket.EndReceive(ar);然后用这个长度去接收数据就没有问题了 可是我怎么得到发送端发的数据长度呢? 如果可以得到那就可以解决了! 
     
    -----------------------------------------------------------------------------------------------------
    一般服务端和客户端都有协议好的,比如最大只发送1024长度字节的数据包,所以你读取到最多也只是1024字节长度的数据,即使客户端发送过长或者出现粘包现象,在你下一次向OS投递BeginReceive的异步请求时,也会立即读取到数据,直到你读取完毕。所以我个人认为,不存在所谓的取得发送端的数据长度,即使有,当初在设计程序的时候,就应该设计好双方的通讯协议一般正常的通讯程序都有着自己的通讯协议
      

  7.   

    先表用类,先测试直接读取信息进行显示,貌似问题就出在类的上面
    昨天下班,没仔细看,抱歉^_^
     private   void   readCallBack(IAsyncResult   ar) 
                    {             Client c = (Client)ar.AsyncState;
                Socket handle = c.Sock;
                int count = 0;
                try
                {
                    count = handle.EndReceive(ar);
                  }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);                CloseSocket(c);//关闭socket
                }
                if (count > 0)
                {
                    byte[] t = new byte[count];
                    Buffer.BlockCopy(c.Message, 0, t, 0, count);
                    string sg = System.Text.Encoding.UTF8.GetString(t);
                    MessageBox.Show(sg);
                    try
                    {
                        handle.BeginReceive(c.Message, 0, c.Message.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack),c);//继续接收
                                        }
                    catch (Exception err)
                    {
                        CloseSocket(c);
                        MessageBox.Show(err.Message);
                    }
                }
                else
                {
                    CloseSocket(c);
                }
                            
      

  8.   

    CloseSocket(c);
    改为
    c.Sock.Close();
      

  9.   

    谢谢各位的关注,
    if (count > 0)
                {
                    byte[] t = new byte[count];
                    Buffer.BlockCopy(c.Message, 0, t, 0, count);
                    string sg = System.Text.Encoding.UTF8.GetString(t);
                    MessageBox.Show(sg);
                    try
                    {
                        handle.BeginReceive(c.Message, 0, c.Message.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack),c);//继续接收
                                        }
                    catch (Exception err)
                    {
                        CloseSocket(c);
                        MessageBox.Show(err.Message);
                    }
                }这样的话,每次接收到信息都会弹出来,如果我一次最大只接收5K的数据,
    而发送端一次就发送了15K的数据,则会分三次接收,所以会弹出三次,理想的结果是:三收完整的数据(这里是三次接收后),再弹出来其实9楼说得对,信息是完整接收了,我就是无法判断什么时候数据完整接收在这里就需要一个协议,如何考虑数据的边界问题?请大家给我出出主意谢谢!
      

  10.   

    这样的话,每次接收到信息都会弹出来,如果我一次最大只接收5K的数据, 
    而发送端一次就发送了15K的数据,则会分三次接收,所以会弹出三次, 
    --------
    这种情况不应该发生吧,一般在开发初期就会确定其接收和发送数据的边界.
    客户端和服务器端的边界应该协调一致.
    理想的结果是:三收完整的数据(这里是三次接收后),再弹出来 
    ----------
    貌似采用这种形式的处理以后,他就不会再显示,就像BookSirSwordsMan 所说,他一直会等到客户端断开.才会显示全部信息
    到时候就不是接收的三次,而是客户端发送的所有信息.
      

  11.   

    哈哈,symbol1441(小红帽),应该是这方面的专家了,哈哈,要学习这样的话,每次接收到信息都会弹出来,如果我一次最大只接收5K的数据,   
    而发送端一次就发送了15K的数据,则会分三次接收,所以会弹出三次,   
    -------- 
    这种情况不应该发生吧,一般在开发初期就会确定其接收和发送数据的边界. 
    客户端和服务器端的边界应该协调一致. 
    -------------------------------------------------------------------------------------
    哈哈,有可能还会发生的,即使定义好边界,可能会因网络原因,而出现粘包现象
    理想的结果是:三收完整的数据(这里是三次接收后),再弹出来   
    ---------- 
    貌似采用这种形式的处理以后,他就不会再显示,就像BookSirSwordsMan   所说,他一直会等到客户端断开.才会显示全部信息 
    到时候就不是接收的三次,而是客户端发送的所有信息. 
    -------------------------------------------------------------------------------------
    这就要靠自己定义协议来,来达到目的
    这个可以看看这个文章http://www.cnblogs.com/wzd24/archive/2007/12/24/1011932.html
      

  12.   

    哈哈,symbol1441(小红帽),应该是这方面的专家了,哈哈,要学习 
    -----------
    我是做WEB的.只是看到这个问题好像见过.所以进来溱热闹来了^_^
    嗯 ,确实应该学习了哈^_^,谢了LS
      

  13.   

    呵呵,偶也是做WEB的但对SOCKET很有兴趣,所以就发问了此问题只针对了文本数据的边界,但如果一旦要发送文件等数据流,那要如何标识呢?如连续发送二个文件,如何标识文件名如何标识文件长度等一系列问题在此抛砖引玉一下希望各位多多指点我决定为此帖加分希望各位拿出Socket的经典部分来分享