关于Socket以不接受时 用BeginReceive 发生接受延时,假若服务器端向客户端连续发送A,B,C 客户端接受的时候总会延迟一次接受到,也就是说当服务器端发B时客户端才能收到A,只有服务器再发送C时,客户端才能收到B,相关代码如下,望各位高手慷慨赐教,谢谢!急
            public void ReceiveData()
{
try
{
StateObject state = new StateObject();
state.workSocket = Soc;
Soc.BeginReceive(state.buffer,0,StateObject.BufferSize,SocketFlags.None,
new AsyncCallback(ReceiveCallback),state);
}
catch(Exception e)
{
RaiseSockErrEvent("Receive : "+e.Message);
                            CloseSocket();
}
} /// <summary>
/// ReceiveData的回调函数
/// </summary>
/// <param name="ar">IAsyncResult实例</param>
private void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;//获得调用时传递的StateObject对象
Socket soc = state.workSocket;
int byteRead = soc.EndReceive(ar);
               
if (byteRead > 0)//判断是否接受到了新信息
{
for(int i=0;i<byteRead;i++)
                                         response.Add(state.buffer[i]);                                   soc.BeginReceive(state.buffer,0,StateObject.BufferSize,SocketFlags.None,
new AsyncCallback(ReceiveCallback),state);//继续接收  问题可能出现在这里 每次都延缓一次才能接受到上次的
}


}
catch(Exception e)
{
RaiseSockErrEvent("Receive : "+e.Message);
                                    CloseSocket();
}
}

解决方案 »

  1.   

    hi  呵呵  我是个初学的哦  用过一点socket  
    “soc.BeginReceive(state.buffer,0,StateObject.BufferSize,SocketFlags.None, 
    new   AsyncCallback(ReceiveCallback),state);//继续接收     问题可能出现在这里   每次都延缓一次才能接受到上次的”
    把这个放到for循环的外面试下
    我也不知道能不能起作用 我也没有去实验  如果不行还希望把我的留言删掉  以免误导别人   呵呵  同时期待解决问题的答案  
      

  2.   

    服务器端发B时客户端才能收到A,只有服务器再发送C时,客户端才能收到B
    -----------------------------------------------------------------
    看样子LZ的代码是客户端的吧,其实在客户端根本就没有必要用异步,这样起不到更好的效果,还会得到相反的效果,异步其实只有在服务器端并且连接客户很多的时候才能达到更好的效果,你说的情况可能就是用了异步造成的
      

  3.   

     改成同步接受还是会存在同样的问题,代码如下
     Thread t;
            public void RecieveDate1()
            {          
                t = new Thread(new ThreadStart(receiveMsg1));
             
                t.Name = "Receive Message";            t.IsBackground = true;
                t.Start();        }
            public void receiveMsg1()
            {
                try
                {
                    while (true)
                    {                    byte[] recvBytes = new byte[1024];
                        int bytes;                    bytes = Soc.Receive(recvBytes, recvBytes.Length, 0);
                     
                        for (int i = 0; i < bytes; i++)
                        {
                            response.Add(recvBytes[i]);
                        }
                        CheckCommand();
                    
                    }            }
                catch (Exception ex)
                {
                    RaiseSockErrEvent("Receive Message Error" + ex.Message);
                    CloseSocket();
                }        }
      

  4.   

    对于TCP来说,同步较容易出现粘包现象,解决的话比较复杂,而异步不存在这个问题,异步出现2个消息到的顺序不一样是很正常的事情,你可以在在消息前加ID,LZ确定用异步还是同步,同步的话把代码贴全点帮你看看
      

  5.   

    to fuadam :
    TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包.
    比如 你先发送了"HELLO",再发送"WORLD",理论上来说可能是会分2次收到,但很有可能一次就收到"HELLOWORLD".
    这种情况还好,很多都是最后一个包并不是完整的,这样出错的概率就会很大
      

  6.   

    我大概帮你改了下,自己用SOCKET测试通过,不会出现你所说的那种情况,你自己在修改下吧.public class Sooo
        {
            byte[] Buff;
            StateObject state;
            public event EventHandler<ReceiveMessage> EventMsg;
            public void ReceiveData()
            {            Buff = new byte[256];
                try
                {
                    state = new StateObject();
                    state.workSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    state.workSocket.Connect(new System.Net.IPAddress(new byte[4] { 192, 168, 2, 97 }), 399);
                    ReceiveDatas(state.workSocket);
                    //Soc.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None,
                    //new AsyncCallback(ReceiveCallback), state);
                }
                catch (Exception e)
                {
                    // RaiseSockErrEvent("Receive   :   " + e.Message);
                    // CloseSocket();
                }
            }        private void ReceiveDatas(Socket socket)
            {
                socket.BeginReceive(Buff, 0, Buff.Length, SocketFlags.None,
                    new AsyncCallback(ReceiveCallback), socket);
            }        ///   <summary> 
            ///   ReceiveData的回调函数 
            ///   </summary> 
            ///   <param   name="ar"> IAsyncResult实例 </param> 
            private void ReceiveCallback(IAsyncResult ar)
            {
                try
                {
                    Socket socket = (Socket)ar.AsyncState;//获得调用时传递的StateObject对象 
                   // Socket soc = state.workSocket;
                    int byteRead = socket.EndReceive(ar);                if (byteRead > 0)//判断是否接受到了新信息 
                    {
                        //for (int i = 0; i < byteRead; i++)
                        //    response.Add(state.buffer[i]);
                        if (EventMsg != null)
                        {
                            ReceiveMessage e = new ReceiveMessage();
                            e.msg = Encoding.Default.GetString(Buff);
                            EventMsg(this, e);
                        }
                        socket.BeginReceive(Buff, 0, Buff.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
                    }
                }
                catch (Exception e)
                {
                    //RaiseSockErrEvent("Receive   :   " + e.Message);
                    // CloseSocket();
                }
            }
        }
       
        public class ReceiveMessage:EventArgs
        {
           public string msg;
        }
        public class StateObject
        {
            public Socket workSocket;
        }
      

  7.   

    谢谢各位,谢谢hopewoo 
        由于这半个月出差,一直没有时间搞这个,按照hopewoo 改的程序测了一下还是会出现问题,就是我写个循环向服务器连发20条信息,每条信息服务器应该给回复,但收到只能收到前三条,地21次发送时才能收到第4条的回复,如果一条一条的发送,能按照顺序接受,没有什么问题
     希望能得到各位进一步的指教,高手们留个邮箱把,我把整个程序发过去帮忙看看。
       我的邮箱[email protected] QQ 272240300 
      

  8.   

    .NET的Socket异步接包似乎偶尔都会出现一点问题,暂时还不知道怎么解决。所以一般尽可能用同步了。
      

  9.   

    [email protected]
    你发给我我帮你看看
      

  10.   

    呵呵 防止粘包推荐用BinaryReader来读,你用字节数等待的话,还是有可能出现问题的.
    我之前也被这个东西弄的头痛死
      

  11.   

    hopewoo 
    花开花落,花落花开 
    等 级:
     发表于:2007-12-13 12:05:4713楼 得分:0 
    非阻塞用于UI上的话,相对友好,如果你接收个大的文件,难道一直让界面处于无响应状态? 
     
       
     
    fuadam 
    路西菲尔 
    等 级:
     发表于:2007-12-13 12:10:1114楼 得分:0 
    同步就会处于无响应,楼上你够搞笑的 
     
       
     
    hopewoo 
    花开花落,花落花开 
    等 级:
     发表于:2007-12-13 12:40:5115楼 得分:0 
    你另开线程来执行这个操作就是另外一回事了.我只是给你举个例子,讲话不要太刻薄你 
     
       
     
    fuadam 
    路西菲尔 
    等 级:
     发表于:2007-12-13 13:00:1316楼 得分:0 
    异步是什么不就是单开线程吗? 
     
       
     
    hopewoo 
    花开花落,花落花开 
    等 级:
     发表于:2007-12-13 13:29:3117楼 得分:0 
    你同步不想阻塞不是也得放在线程里吗?难道挂在主线程里? 
     
     
       
     
    hopewoo 
    花开花落,花落花开 
    等 级:
     发表于:2007-12-13 13:35:1518楼 得分:0 
    不说这个了,反正各有各的好处,异步存在就肯定有它的价值,同步对传输来说效率是很高,但对于全局程序就不一定,这个道理就和多开线程能提高程序运行效率是一样的.你说"从来就没觉得非阻塞方式有多大用"这话就有点偏激了. 
    还是帮LZ解决问题吧 
     
    -----------------------------------------------------------------------------------------
    我不想批什么,只是想说TO:fuadam
    一般的服务器程序如果在连接多的情况下都是要用导步的,你所说的“同步就会处于无响应,楼上你够搞笑的”点有那个的味道,如果你用同步没有另开线程的话,UI界面肯定处于假死的状态,一般的.NET同步通讯程序,都是另开线程来接受连接的,这样很不好,如果有1000个连接就开1000个?性能肯定很低下的。导步通讯程序虽然并没有直接使用线程,但也是用了线程,不过这个异步的线程是丢到系统内核去的,甚至是硬件级别上的,这样性能就得到很大的提升了。如果不相信,你可以直接写一个程序试一下我觉得hopewoo对.NET的网络通讯还是理解得比较清楚的,呵呵