解决方案 »

  1.   

    一次能接收的数据长度取决于buffer.Length和socket.Available,后者是协议缓冲区收到的未读取数据。注意,当发送方发过来的数据量较大或者网络不太好时,缓冲区很可能一次收不完所有数据,所以通常是收发双方协定一个接收完的认定模式。比如让发送方把数据总长度(long)放在最前面的8字节,接收方先读取首8字节,转成long,然后在循环receive时判断已收到的长度
      

  2.   

    一般是自定义一个类,比如: public class StateObject
            {
                public TcpClient Client = null;           
                public byte[] buffer = new byte[1024];        
                public MemoryStream mb = new MemoryStream();
            }
    开始 的时候:
    static void Main(string[] args)
            {
                //创建一个Socket
                var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                try
                {   //连接到指定服务器的指定端口
                    socket.Connect("192.168.2.80", 40012);
                    Console.WriteLine("{0}:{1}:Conneted...." + "\r\n", "192.168.2.80", 40012);
                    //实现接受消息的方法
    StateObject o=bew StateObject();
    o.Client=socket;
                    socket.BeginReceive(o.buffer , 0,o.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), o);
                    Console.Read();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
    接收到数据的时候:
     
    TcpClient client=null;
                StateObject state = (StateObject)ar.AsyncState;   
                    // 从输入参数异步state对象中获取state和socket对象                  
                    client = state.Client;
                    //从远程设备读取数据                
                    int bytesRead = client.Client.EndReceive(ar);  
                    if (bytesRead > 0)
                    {
                        // 有数据,存储.
                            state.mb.Write(state.buffer,0, state.buffer.Length);           
                        // 继续读取.  
                        if (client.Client.Available > 0)
                        {
                            client.Client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
                        }
                        else
                        {//接收完成,做处理}
    大概是这么个意思
      

  3.   


    不是“每天这类问题很多”,实在是这种问题是最基本的概念,却每天就好像发现自称小学毕业的人被发现“1+2=3等于都没有理解”的人。假设对方连续发送了1000、200个字节的两块数据,接收端可能一次接收到1200字节,也可能分900字节、200字节、100字节三次接收到,因为tcp本来就是“慢启动、自动拆包、自动粘包”的。这完全看发送端机器的忙闲程度、网络通讯状况而定。所以在本地、单机上的简单测试不算数。有个这个基本概念,再来看一个人的程序写的是否正确。不能理解这个基本概念,多说无益。
      

  4.   

    我们不厌其烦地说“要循环多地Revceive/Read”,这其实就等于给自称小学毕业的人重新讲数字加减法,是不得已的。我真的不愿意看到csdn整天讨论这个问题,但是许多问题、许多“数据过长,所以无法一次接收完成”之类的话都是这个陷阱而引起的。
      

  5.   


    谢谢回复,你这个类里面是装的什么?自己定于的? StateObject类
      

  6.   


    我把你的代码整理修改了一下,但是有一个地方转换不了 //实现接受消息的方法
                    StateObject o = new StateObject();
                    o.Client = socket;这个地方 TCPclint和Socket之间?是不是哪里有误?还是
    public class StateObject
        {
            public TcpClient Client = null;
            public byte[] buffer = new byte[1024];
            public MemoryStream mb = new MemoryStream();
            public const int BufferSize = 1024;
        }    class Program
        {
            static byte[] buffer = new byte[2048];
            static void Main(string[] args)
            {
                //创建一个Socket
                var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                try
                {   //连接到指定服务器的指定端口
                    socket.Connect("192.168.0.80", 4001);
                    Console.WriteLine("{0}:{1}:Conneted...." + "\r\n", "192.168.0.80", 4001);
                    //实现接受消息的方法
                    StateObject o = new StateObject();
                    o.Client = socket;
                    socket.BeginReceive(o.buffer, 0, o.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), o);
                    Console.Read();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }        /// <summary>
            /// 异步接收数据
            /// </summary>
            /// <param name="ar"></param>
            public static void ReceiveMessage(IAsyncResult ar)
            {
                TcpClient client = null;
                StateObject state = (StateObject)ar.AsyncState;
                // 从输入参数异步state对象中获取state和socket对象                  
                client = state.Client;
                //从远程设备读取数据                
                int bytesRead = client.Client.EndReceive(ar);
                if (bytesRead > 0)
                {
                    // 有数据,存储.
                    state.mb.Write(state.buffer, 0, state.buffer.Length);
                    // 继续读取.  
                    if (client.Client.Available > 0)
                    {
                        client.Client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveMessage), state);
                    }
                    else
                    {
                        //接收完成,做处理
                    }
                }
            }
      

  7.   


    你自己写代码 var socket = ar.AsyncState as Socket; 时就没想过 AsyncState 属性可以保存自己愿意传送的任意类型的参数?
      

  8.   


    我把你的代码整理修改了一下,但是有一个地方转换不了 //实现接受消息的方法
                    StateObject o = new StateObject();
                    o.Client = socket;这个地方 TCPclint和Socket之间?是不是哪里有误?还是
    public class StateObject
        {
            public TcpClient Client = null;
            public byte[] buffer = new byte[1024];
            public MemoryStream mb = new MemoryStream();
            public const int BufferSize = 1024;
        }    class Program
        {
            static byte[] buffer = new byte[2048];
            static void Main(string[] args)
            {
                //创建一个Socket
                var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                try
                {   //连接到指定服务器的指定端口
                    socket.Connect("192.168.0.80", 4001);
                    Console.WriteLine("{0}:{1}:Conneted...." + "\r\n", "192.168.0.80", 4001);
                    //实现接受消息的方法
                    StateObject o = new StateObject();
                    o.Client = socket;
                    socket.BeginReceive(o.buffer, 0, o.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), o);
                    Console.Read();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }        /// <summary>
            /// 异步接收数据
            /// </summary>
            /// <param name="ar"></param>
            public static void ReceiveMessage(IAsyncResult ar)
            {
                TcpClient client = null;
                StateObject state = (StateObject)ar.AsyncState;
                // 从输入参数异步state对象中获取state和socket对象                  
                client = state.Client;
                //从远程设备读取数据                
                int bytesRead = client.Client.EndReceive(ar);
                if (bytesRead > 0)
                {
                    // 有数据,存储.
                    state.mb.Write(state.buffer, 0, state.buffer.Length);
                    // 继续读取.  
                    if (client.Client.Available > 0)
                    {
                        client.Client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveMessage), state);
                    }
                    else
                    {
                        //接收完成,做处理
                    }
                }
            }

    其实意思到了,你改下就行了。不管是TcpClient还是Socket,都一样,类型不对,你改下不好了,思路是这样的。我只能帮你到这里了