struct socketObject
    {
        public Socket soc;
        public int sendedLen;
        public socketObject(Socket soc, int len)
        {
            this.soc = soc;
            this.sendedLen = len;
        }
    }
    public class FileTransServer:IFileTransServer 
    {
        private string _filePath;
        private int _bufferSize=1024*1024;
        private byte[] _dataBuffer = null;
        private int _port=1000;
        private Socket _socket;
        private FileStream _fs = null;        private int x;        public string filePath
        {
            get
            {
                return _filePath;
            }
            set
            {
                _filePath = value;
            }        }
        public int bufferSize
        {
            get
            {
                return _bufferSize;
            }
            set
            {
                _bufferSize = value;
            }
        }
        public int port
        {
            get
            {
                return _port;
            }
            set
            {
                _port = value;
            }
        }
        public Boolean receive()
        {
            try
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, _port);
                _socket.Bind(endPoint);
                _socket.Listen(1);
                _socket.BeginAccept(new AsyncCallback(onAccept), null);
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }
        private void onAccept(IAsyncResult ar)
        {
           Socket soc=_socket.EndAccept(ar);
            _dataBuffer =new byte [_bufferSize ];
            soc.BeginReceive(_dataBuffer, 0, _dataBuffer.Length, SocketFlags.None,new AsyncCallback (onReceiveFileName),soc);
        }
        private void onReceiveFileName(IAsyncResult ar)//接收文件名
        {
            Socket soc = (Socket)(ar.AsyncState);
            int len = soc.EndReceive(ar);
            if (len == 0)
            {
                soc.Shutdown(SocketShutdown.Both);
                soc.Close();
                _fs.Close();
            }
            else
            {
                string fileName = Encoding.UTF8.GetString(_dataBuffer,4,BitConverter.ToInt32(_dataBuffer,0));
                _fs = new FileStream(_filePath+fileName, FileMode.Create, FileAccess.Write);
               _fs.Write(_dataBuffer,4 + BitConverter.ToInt32(_dataBuffer, 0), len - (4 + BitConverter.ToInt32(_dataBuffer, 0)));
               x=x+len - (4 + BitConverter.ToInt32(_dataBuffer, 0));
               // string fileName = "aa.rar";
                //_fs = new FileStream(_filePath + fileName, FileMode.Create, FileAccess.Write);
                //_fs.Write(_dataBuffer, 0, len);
                soc.BeginReceive(_dataBuffer, 0, _dataBuffer.Length, SocketFlags.None, new AsyncCallback(onReceive), soc);
            }
        }
        private void onReceive(IAsyncResult ar)
        {
            Socket soc = (Socket )(ar.AsyncState);
            int len = soc.EndReceive(ar);
            if (len == 0)
            {
                soc.Shutdown(SocketShutdown.Both);
                soc.Close();
                _fs.Close();
                System.Console.WriteLine("总接收:" + x);
            }
            else
            {
                _fs.Write(_dataBuffer, 0, len);
                x = x + len;
                System.Console.WriteLine("已接收:" + x);
                soc.BeginReceive(_dataBuffer, 0, _dataBuffer.Length, SocketFlags.None, new AsyncCallback(onReceive), soc );
            }
        }
    }
    public class FileTransClient : IFileTransClient
    {
        private string _filePath;
        private int _bufferSize = 1024 * 1024;//此处如果设为1024*64传输文件没有问题,如果是1024*1024传输大文件会出现问题
        private byte[] _dataBuffer = null;
        private int _port = 1000;
        private string _serverName;
        private Socket _socket;
        private FileStream _fs = null;
        private int _sendedLen;
        private Boolean _isEnd = false;//是否发送完毕
        private Boolean _isOk = false;//发送成功与否
        public string filePath
        {
            get
            {
                return _filePath;
            }
            set
            {
                _filePath = value;
            }
        }
        public int bufferSize
        {
            get
            {
                return _bufferSize;
            }
            set
            {
                _bufferSize = value;
            }
        }
        public int port
        {
            get
            {
                return _port;
            }
            set
            {
                _port = value;
            }
        }
        public string serverName
        {
            get
            {
                return _serverName;
            }
            set
            {
                _serverName = value;
            }
        }
        public int sendedLen
        {
            get
            {
                return _sendedLen;
            }
        }
        public Boolean send()
        {
            try
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ip = Dns.GetHostByName(_serverName).AddressList[0];
                IPEndPoint endPoint = new IPEndPoint(ip, 1000);
                _socket.BeginConnect(endPoint, new AsyncCallback(onConnect), _socket);
                while (!_isEnd)
                {
                    Thread.Sleep(500);
                }
            }
            catch (Exception ex)
            {
                return false;
            }
            return _isOk ;
        }
        public void onConnect(IAsyncResult ar)
        {
            try
            {
                Socket soc = (Socket)ar.AsyncState;
                soc.EndConnect(ar);
                //发送文件名长度及文件名
                string fileName = _filePath.Substring (_filePath.LastIndexOf (@"\")+1);
                int fileNameLen = fileName.Length;
                List<byte> result = new List<byte>();
                result.AddRange(BitConverter.GetBytes(Encoding.UTF8.GetBytes(fileName).Length ));
               // result.AddRange(BitConverter.GetBytes(fileName.Length));
                result.AddRange(Encoding.UTF8.GetBytes(fileName));
                byte[] dataTmp=result.ToArray();
                soc.BeginSend(dataTmp, 0, dataTmp.Length , SocketFlags.None, new AsyncCallback(onSend), new socketObject(soc, 0));
                //发送文件
                _fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
                int readLength = 0;
                long fileLen = _fs.Length;
                _dataBuffer = new byte[_bufferSize];
                while ((readLength = _fs.Read(_dataBuffer, 0, _dataBuffer.Length)) > 0)
                {
                    soc.BeginSend(_dataBuffer, 0, readLength, SocketFlags.None, new AsyncCallback(onSend), new socketObject(soc, readLength));
                    //Thread.Sleep(500);                }
                _fs.Close();
                while (_sendedLen < fileLen)
                {
                    System.Console.WriteLine("已发送:" + _sendedLen +"总大小:"+ fileLen);
                    Thread.Sleep(500);
                }                
                soc.Shutdown(SocketShutdown.Both);
                soc.Close();
                _sendedLen = 0;
                _isOk = true;//此处执行则表示发送成功
                _isEnd = true;
            }catch(Exception ex)
            {
                _isOk = false;
                _isEnd = true;            }
           
           
        }
        public void onSend(IAsyncResult ar)
        {
            try
            {
                socketObject socObj = (socketObject)ar.AsyncState;
                Socket soc = socObj.soc;
                soc.EndSend(ar);
                System.Object lockThis = new System.Object();
                lock (lockThis)
                {
                    _sendedLen = _sendedLen + socObj.sendedLen;               
                }
                System.Console.WriteLine("已发送:" + _sendedLen );
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
                _isOk = false;
                _isEnd = true;
            }            
        }    }

解决方案 »

  1.   

    自己搞定了!!!
    while ((readLength = _fs.Read(_dataBuffer, 0, _dataBuffer.Length)) > 0)
                    {
                        soc.BeginSend(_dataBuffer, 0, readLength, SocketFlags.None, new AsyncCallback(onSend), new socketObject(soc, readLength));
                        //Thread.Sleep(500);                }
    应改为
    while ((readLength = _fs.Read(_dataBuffer, 0, _dataBuffer.Length)) > 0)
                    {
                        soc.BeginSend(_dataBuffer, 0, readLength, SocketFlags.None, new AsyncCallback(onSend), new socketObject(soc, readLength));
                         _dataBuffer = new byte[_bufferSize];
                        //Thread.Sleep(500);                }
      

  2.   

    在异步程序中,你的那个
       soc.Shutdown(SocketShutdown.Both);
    永远都不会执行!怎么可能len==0呢?想过没有?另外,虽然你的buffer有1M只巨大,可是你传递的东西难道都不大于1M吗?至于说发送方使用 BeginSend,这就存在“乱序”的可能,而  _dataBuffer = new byte[_bufferSize] 只是头痛医头脚疼医脚而已。
      

  3.   


    这位老兄,在文件传输完毕之后,client端就会关闭socket,server端就会使len=0
    还有,client端读文件是每次读取_bufferSize个字节,所有没有问题,
    谢谢你的回复
      

  4.   

    个人理解,使用tcp进行传输,是可保证数据包按序到达的,是不存在“乱序”的可能,除非是udp,则有可能出现乱序的可能。