我服务端通过SOCKET向客户端发送大数据(M以上的数据),数据大后,容易掉包,用多线程的话不掉包,但是速度又比较慢了。请教各位大神了!

解决方案 »

  1.   

    <code C#>
    const int blockLength=512*1024;
    public void SendFile(string filePath, NetworkStream stream)     //发送文件
            {
                //传输内容
                using (FileStream fs = File.Open(filePath, FileMode.Open))
                {
                    int readLength = 0;
                    byte[] data = new byte[blockLength];                //发送大小
                    byte[] length = new byte[8];
                    BitConverter.GetBytes(new FileInfo(filePath).Length).CopyTo(length, 0);
                    stream.Write(length, 0, 8);                //发送文件
                    while ((readLength = fs.Read(data, 0, blockLength)) > 0)
                    {
                        stream.Write(data, 0, readLength);
                    }
                }        }public bool ReceiveFile(string fileName, NetworkStream stream) //接收文件
            {
                try
                {
                    long count = GetSize(stream);
                    if (count == 0)
                    {
                        return false;
                    }
                    long index = 0;
                    int currentBlockLength = 0;
                    int receivedBytesLen = 1;
                    using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate))
                    {
                        while (receivedBytesLen > 0 && index < count)
                        {
                            byte[] clientData = new byte[blockLength];
                            receivedBytesLen = 0;                        if (blockLength < count - index)
                            {
                                currentBlockLength = blockLength;
                            }
                            else
                            {
                                currentBlockLength = (int)(count - index);
                            }
                            receivedBytesLen = stream.Read(clientData, 0, currentBlockLength);
                            fs.Write(clientData, 0, receivedBytesLen);
                            index += receivedBytesLen;
                        }
                    }
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return false;
                }
                return true;
            }private int GetSize(NetworkStream stream) //获取文件大小
            {
                int count = 0;
                byte[] countBytes = new byte[8];
                try
                {
                    if (stream.Read(countBytes, 0, 8) == 8)
                    {
                        count = BitConverter.ToInt32(countBytes, 0);
                    }
                    else
                    {
                        return 0;
                    }
                }
                catch
                {
                    return 0;
                }
                return count;
            }
    </code>
      

  2.   


    为何不行?每次写入的大小最大是512KB,再大的文件也没事呀,那个GetSize函数的返回类型改成long,不会有文件比这个还大吧
      

  3.   

    网络传输主要耗时原因在于网络环境,弄个56k的猫1MB你也要传个几分钟。
    600Gb光纤1G也要不了一分钟。
      

  4.   

    不是协议的问题,应该是代码处理上! 以下为微软发送文件 sendfile函数源码!
    // System.Net.Sockets.Socket
    public void SendFile(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
    {
    if (Socket.s_LoggingEnabled)
    {
    Logging.Enter(Logging.Sockets, this, "SendFile", "");
    }
    if (this.CleanedUp)
    {
    throw new ObjectDisposedException(base.GetType().FullName);
    }
    if (!ComNetOS.IsWinNt)
    {
    throw new PlatformNotSupportedException(SR.GetString("WinNTRequired"));
    }
    if (!this.Connected)
    {
    throw new NotSupportedException(SR.GetString("net_notconnected"));
    }
    this.ValidateBlockingMode();
    TransmitFileOverlappedAsyncResult transmitFileOverlappedAsyncResult = new TransmitFileOverlappedAsyncResult(this);
    FileStream fileStream = null;
    if (fileName != null && fileName.Length > 0)
    {
    fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
    }
    SafeHandle safeHandle = null;
    if (fileStream != null)
    {
    ExceptionHelper.UnmanagedPermission.Assert();
    try
    {
    safeHandle = fileStream.SafeFileHandle;
    }
    finally
    {
    CodeAccessPermission.RevertAssert();
    }
    }
    SocketError socketError = SocketError.Success;
    try
    {
    transmitFileOverlappedAsyncResult.SetUnmanagedStructures(preBuffer, postBuffer, fileStream, TransmitFileOptions.UseDefaultWorkerThread, true);
    if ((safeHandle != null) ? (!UnsafeNclNativeMethods.OSSOCK.TransmitFile_Blocking(this.m_Handle.DangerousGetHandle(), safeHandle, 0, 0, SafeNativeOverlapped.Zero, transmitFileOverlappedAsyncResult.TransmitFileBuffers, flags)) : (!UnsafeNclNativeMethods.OSSOCK.TransmitFile_Blocking2(this.m_Handle.DangerousGetHandle(), IntPtr.Zero, 0, 0, SafeNativeOverlapped.Zero, transmitFileOverlappedAsyncResult.TransmitFileBuffers, flags)))
    {
    socketError = (SocketError)Marshal.GetLastWin32Error();
    }
    }
    finally
    {
    transmitFileOverlappedAsyncResult.SyncReleaseUnmanagedStructures();
    }
    if (socketError != SocketError.Success)
    {
    SocketException ex = new SocketException(socketError);
    this.UpdateStatusAfterSocketError(ex);
    if (Socket.s_LoggingEnabled)
    {
    Logging.Exception(Logging.Sockets, this, "SendFile", ex);
    }
    throw ex;
    }
    if ((transmitFileOverlappedAsyncResult.Flags & (TransmitFileOptions.Disconnect | TransmitFileOptions.ReuseSocket)) != TransmitFileOptions.UseDefaultWorkerThread)
    {
    this.SetToDisconnected();
    this.m_RemoteEndPoint = null;
    }
    if (Socket.s_LoggingEnabled)
    {
    Logging.Exit(Logging.Sockets, this, "SendFile", socketError);
    }
    }