简体   繁体   中英

Socket.Send, server receive many invalid MPacket

[Serializable]
public class Packet : ISerializable

Packet is my class use for holding data, implemented ISerializable and all needed constructor and functions I read from [ http://msdn.microsoft.com/en-us/library/ms182342.aspx]

[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
private void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
protected Packet(SerializationInfo info, StreamingContext context)

I put my Packet inside a dll and reference it in both server and client application so they can transfer Packet using TcpListener (convert to byte[] and send, received and convert back)

I tested server-client worked perfectly with single Packet without sending file or less-or-equals 1mb file. This is server log when it received a Packet with rename command from client

[7174c67d-518f-4960-affe-d3bc67320d7e] Waiting for message
20/07/2014 13:03:48: {Rename} SUCCESS from 7174c67d-518f-4960-affe-d3bc67320d7e to NewName

Each Packet, it put maximum 1mb length byte array as file part's data on byte[] msgFileData property and TcpListener receive maximum 2mb.

The problem is when sending a more-than-1mb file, I splited that file into parts which maximum 1mb per-each and only some Packets received with correct format, can deserizable and some are Invalid Packet format. A little time it worked and usually show this error so I can only upload if I upload it in a lucky moment

        20/07/2014 13:03:48: {Rename} SUCCESS from 7174c67d-518f-4960-affe-d3bc67320d7e to NewName
    20/07/2014 13:03:48: [NewName] Waiting for message
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Uploaded 1/5 part of AMediumFile5mb.mp3 (Guid 40695b81-18b1-4329-bb00-344474458c47) from NewName
    20/07/2014 13:04:22: Uploaded 2/5 part of AMediumFile5mb.mp3 (Guid 40695b81-18b1-4329-bb00-344474458c47) from NewName
    20/07/2014 13:04:22: Error Packet: System.Runtime.Serialization.SerializationException: Binary stream '228' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
       at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
       at engine.converter.prjnameConverter.BinaryDeserializeObject[T](Byte[] serializedType) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 74
       at engine.converter.prjnameConverter.DeSerializeFromByteArray[T](Byte[] data) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 52
       at prjname.entity.Client.readResponsePacket(Byte[] data, Packet& Packet, Boolean& bValidPacket) in d:\Work\C#\Project\Work\prjname-Server\entity\Client.cs:line 154
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Uploaded 3/5 part of AMediumFile5mb.mp3 (Guid 40695b81-18b1-4329-bb00-344474458c47) from NewName
    20/07/2014 13:04:22: Error Packet: System.Runtime.Serialization.SerializationException: The input stream is not a valid binary format. The starting contents (in bytes) are: 30-0A-00-80-B2-98-3D-A7-FC-B4-41-FC-4F-02-81-03-8A ...
       at System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(__BinaryParser input)
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadSerializationHeaderRecord()
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
       at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
       at engine.converter.prjnameConverter.BinaryDeserializeObject[T](Byte[] serializedType) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 74
       at engine.converter.prjnameConverter.DeSerializeFromByteArray[T](Byte[] data) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 52
       at prjname.entity.Client.readResponsePacket(Byte[] data, Packet& Packet, Boolean& bValidPacket) in d:\Work\C#\Project\Work\prjname-Server\entity\Client.cs:line 154
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Error Packet: System.Runtime.Serialization.SerializationException: The input stream is not a valid binary format. The starting contents (in bytes) are: 2B-01-83-40-2E-12-63-8F-C7-F6-89-B2-40-8C-CC-86-2E ...
       at System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(__BinaryParser input)
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadSerializationHeaderRecord()
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
       at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
       at engine.converter.prjnameConverter.BinaryDeserializeObject[T](Byte[] serializedType) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 74
       at engine.converter.prjnameConverter.DeSerializeFromByteArray[T](Byte[] data) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 52
       at prjname.entity.Client.readResponsePacket(Byte[] data, Packet& Packet, Boolean& bValidPacket) in d:\Work\C#\Project\Work\prjname-Server\entity\Client.cs:line 154
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Error Packet: System.Runtime.Serialization.SerializationException: Binary stream '57' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
       at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
       at engine.converter.prjnameConverter.BinaryDeserializeObject[T](Byte[] serializedType) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 74
       at engine.converter.prjnameConverter.DeSerializeFromByteArray[T](Byte[] data) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 52
       at prjname.entity.Client.readResponsePacket(Byte[] data, Packet& Packet, Boolean& bValidPacket) in d:\Work\C#\Project\Work\prjname-Server\entity\Client.cs:line 154
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Error Packet: System.Runtime.Serialization.SerializationException: The input stream is not a valid binary format. The starting contents (in bytes) are: AA-01-17-58-02-01-40-C1-D1-51-10-38-29-A8-D5-68-C0 ...
       at System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(__BinaryParser input)
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadSerializationHeaderRecord()
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
       at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
       at engine.converter.prjnameConverter.BinaryDeserializeObject[T](Byte[] serializedType) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 74
       at engine.converter.prjnameConverter.DeSerializeFromByteArray[T](Byte[] data) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 52
       at prjname.entity.Client.readResponsePacket(Byte[] data, Packet& Packet, Boolean& bValidPacket) in d:\Work\C#\Project\Work\prjname-Server\entity\Client.cs:line 154
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Error Packet: System.Runtime.Serialization.SerializationException: Binary stream '150' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
       at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
       at engine.converter.prjnameConverter.BinaryDeserializeObject[T](Byte[] serializedType) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 74
       at engine.converter.prjnameConverter.DeSerializeFromByteArray[T](Byte[] data) in d:\Work\C#\Project\Work\prjnameDll\converter\prjnameConverter.cs:line 52
       at prjname.entity.Client.readResponsePacket(Byte[] data, Packet& Packet, Boolean& bValidPacket) in d:\Work\C#\Project\Work\prjname-Server\entity\Client.cs:line 154
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Uploaded 4/5 part of AMediumFile5mb.mp3 (Guid 40695b81-18b1-4329-bb00-344474458c47) from NewName

It has to be something like this

    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Uploaded 1/5 part of AMediumFile5mb.mp3 (Guid 40695b81-18b1-4329-bb00-344474458c47) from NewName
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Uploaded 2/5 part of AMediumFile5mb.mp3 (Guid 40695b81-18b1-4329-bb00-344474458c47) from NewName
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Uploaded 3/5 part of AMediumFile5mb.mp3 (Guid 40695b81-18b1-4329-bb00-344474458c47) from NewName
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Uploaded 4/5 part of AMediumFile5mb.mp3 (Guid 40695b81-18b1-4329-bb00-344474458c47) from NewName
    20/07/2014 13:04:22: [NewName] Waiting for message
    20/07/2014 13:04:22: Uploaded 5/5 part of AMediumFile5mb.mp3 (Guid 40695b81-18b1-4329-bb00-344474458c47) from NewName

**********Client*************

MainForm.cs

private void uploadFileToServerToolStripMenuItem_Click(object sender, EventArgs e)
    {
        OpenFileDialog dlgChooseUploadFile = new OpenFileDialog();
        dlgChooseUploadFile.Multiselect = false;
        /*some code*/
        if (dlgChooseUploadFile.ShowDialog() == DialogResult.OK)
        {
            /*some code*/
            string strFilePath = dlgChooseUploadFile.FileName;
            muUser.Upload(strFilePath); //muUser is class User
        }
    }

User.cs

    public void Upload(string strFilePath)
    {
        OnLockForm(true); // Disable MainForm while uploading
        UploadingForm uploader = new UploadingForm(strFilePath, this);//=> this: pass user as parameter to get user info like name, NetworkStream for sending request
        uploader.OnStopUpload += new UploadingForm.StopUpload((string strMessage)=>
        {
            OnLockForm(false);
            OnNotifyMessage(strMessage);
        });
        uploader.ShowDialog();
    }

UploadingForm.cs

public partial class UploadingForm : Form
{
    public delegate void StopUpload(string strMessage);
    public StopUpload OnStopUpload;
    private string mstrFilePath;
    private User sender;
    public UploadingForm(string strFilePath, User sender)
    {
        CheckForIllegalCrossThreadCalls = false;
        this.mstrFilePath = strFilePath;
        this.sender = sender;
        InitializeComponent();
    }

    private void UploadingForm_Shown(object sender, EventArgs e)
    {
        //some code
        ParepareUpload();
    }
    private void ParepareUpload()
    {
        Uploader uploader = new Uploader(mstrFilePath, sender);
        uploader.OnAPartUploaded += new Uploader.APartUploaded(()=>
        {
            /*some code but I disabled this delegate*/
        });
        uploader.OnUploadCanceled+= new Uploader.UploadCancel((string strReason)=>
        {
            OnStopUpload(strReason);
            this.Dispose();
        });
        uploader.OnUploadCompleted += new Uploader.UploadCompleted(() =>
        {
            OnStopUpload("Upload done");
            this.Dispose();
        });
        uploader.Begin();
    }

Uploader.cs

public class Uploader
{
    public delegate void UploadCompleted();
    public UploadCompleted OnUploadCompleted;
    public delegate void APartUploaded();
    public APartUploaded OnAPartUploaded;
    public delegate void UploadCancel(string strReason);
    public UploadCancel OnUploadCanceled;

    public string mstrFilePath { get; private set; }
    public string mUserName { get; private set; }
    public Guid mGuid { get; private set; }
    private NetworkStream mnetStream { get; set; }

    public Uploader(string strFilePath, User sender)
    {
        this.mGuid = Guid.NewGuid();
        this.mUserName = sender.mstrName;
        this.mstrFilePath = strFilePath;
        this.mnetStream = sender.netStream;
    }

    public void Begin()
    {
        /*some code*/
        BeginUploadFile();
    }

    private void BeginUploadFile()
    {
        try
        {
            string strFileName = Path.GetFileName(mstrFilePath);
            long lFileSize = new FileInfo(mstrFilePath).Length;
            byte iPartsCount = (byte)Math.Ceiling((decimal)lFileSize / engine.data.Packet.PACKET_MAXSIZE_UPLOADPART);
            for (byte i = 1; i <= iPartsCount; i++)
            {
                int numBytesToRead = Packet.PACKET_MAXSIZE_UPLOADPART;
                if (i == iPartsCount)
                {
                    numBytesToRead = (int)(lFileSize - ((i - 1) * Packet.PACKET_MAXSIZE_UPLOADPART));
                }
                sendPacket(Packet.CreatePFileUpload(strFileName, i, iPartsCount, readPartOfFile(Packet.PACKET_MAXSIZE_UPLOADPART * (i - 1), numBytesToRead), mGuid));
            }
            OnUploadCompleted();
        }
        catch (Exception ex)
        {
            OnUploadCanceled(ex.ToString());
        }
    }

    private object sync_readPartOfFile = new object();
    private byte[] readPartOfFile(int iByteFrom, int numBytesToRead)
    {
        lock (sync_readPartOfFile)
            try
            {
                using (FileStream fsSource = new FileStream(mstrFilePath, FileMode.Open, FileAccess.Read))
                {
                    fsSource.Seek(iByteFrom, SeekOrigin.Begin);
                    iByteFrom = 0;
                    long lEnd = fsSource.Length;
                    // Read the source file into a byte array.
                    byte[] bytes = new byte[numBytesToRead];
                    while (numBytesToRead > 0)
                    {
                        // Read may return anything from iByteFrom to numBytesToRead. 
                        int n = fsSource.Read(bytes, iByteFrom, numBytesToRead);

                        // Break when the end of the file is reached. 
                        if (n == 0)
                            break;

                        iByteFrom += n;
                        numBytesToRead -= n;
                    }
                    return bytes;
                }
            }
            catch
            {
                throw;
            }
    }

    private object sync_sendRequest = new object();
    private void sendPacket(Packet request)
    {
        lock (sync_sendRequest)
            try
            {
                request.pkOwner = mUserName;
                byte[] buffer = weHereConverter.SerizableObject(request);
                mnetStream.Write(buffer, 0, buffer.Length);
                mnetStream.Flush();
                //OnAPartUploaded(); /*tempolary disabled*/
            }
            catch (Exception)
            {
                throw;
            }
    }

********SERVER**********

ClientManager.cs // hold list of clients

    public void Listen(TcpClient tcpClient, string strName)
    {
        Client client = new Client(tcpClient, strName);
        client.OnNotifyDisconnect += new Client.NotifyDisconnect(ClientDisconnect);
        client.OnNotifyMessage += new Client.NotifyMessage(ClientMessage);
        client.OnNotifyReceivedData += new Client.NotifyReceivedData(ClientReceivedData);
        lock (sync_mlistClient)
        {
            Packet pkNotifySignIn = Packet.CreatePServerNotify("*ding* welcome...someone");
            foreach (Client c in mlistClient)
            {
                try
                {
                    c.send(pkNotifySignIn);
                }
                catch { }
            }
            mlistClient.Add(client);
        }
        client.BeginListen();
    }

    private void ClientReceivedData(Packet pkData, Client client)
    {
        if (pkData.isSCmd())
        {
            if (pkData.ScmdType == Command.SCMD_RENAME) // packet rename
            {
                /*some code*/
            }
            else if (pkData.ScmdType == Command.SCMD_FILEUPLOAD)
            {
                //new Thread(() => thread_UploadFile(pkData)).Start();
                thread_UploadFile(pkData);
            }
            else
            {
                /*some code*/
            }
        }
        else if (pkData.isMessage())
        {
            new Thread(() => ForwardMessageToClient(pkData, client)).Start();
        }
        else
        {
            /*some code*/
        }
    }

    // named thread but I call it like a normal method
    private void thread_UploadFile(Packet pkUploadData)
    {
        //new Thread(() => thread_OnUploadingFile(pkUploadData)).Start();
        thread_OnUploadingFile(pkUploadData);
    }

    private object sync_thread_OnUploadingFile = new object();
    private void thread_OnUploadingFile(Packet pkUploadData)
    {
        lock (sync_thread_OnUploadingFile)
        {
            FileUploadInfo uploadInfo = getFileUploadInfo(pkUploadData);
            if (uploadInfo.Fail) // reject packet, Fail marked as true when exception occured while writing to server's hard disk
                return;
            try
            {
                File.WriteAllBytes(getUploadFilePart(pkUploadData.ScmdFileUploadGuid, pkUploadData.ScmdFileUploadPartNumber), pkUploadData.msgFileData);
            }
            catch (Exception ex)
            {
                /*server log*/MakeThreadNotifyMessage("Error while uploading part " + pkUploadData.ScmdFileUploadPartNumber + "/" + pkUploadData.ScmdFileUploadPartsCount + " of " + pkUploadData.ScmdFileUploadName + " (Guid " + pkUploadData.ScmdFileUploadGuid + ") from " + pkUploadData.pkOwner + "\r\n" + ex);
                uploadInfo.Fail = true;
            }
            finally
            {
                uploadInfo.OnAPartUploaded(); // increase count part uploaded in uploadInfo
                if (!uploadInfo.Complete)
                    /*server log*/MakeThreadNotifyMessage("Uploaded " + uploadInfo.CountPartsUploaded + "/" + pkUploadData.ScmdFileUploadPartsCount + " part of " + pkUploadData.ScmdFileUploadName + " (Guid " + pkUploadData.ScmdFileUploadGuid + ") from " + pkUploadData.pkOwner);
            }
        }
    }

    private Dictionary<Guid, FileUploadInfo> mdictFileUpload = new Dictionary<Guid, FileUploadInfo>();
    private object sync_mdictFileUpload = new object();
    private FileUploadInfo getFileUploadInfo(Packet pkUploadData)
    {
        lock (sync_mdictFileUpload)
        {
            FileUploadInfo result;
            if (!mdictFileUpload.TryGetValue(pkUploadData.ScmdFileUploadGuid, out result))
            {
                mdictFileUpload.Add(pkUploadData.ScmdFileUploadGuid, result = new FileUploadInfo(
                        pkUploadData.pkOwner, // uploader's name
                        pkUploadData.ScmdFileUploadGuid, // file guid because I save on save like G-U-I-D-filename_partposition.part
                        pkUploadData.ScmdFileUploadName,  // file name
                        pkUploadData.ScmdFileUploadPartsCount // total parts count, ex: 5mb file will be splited into 5 parts
                        ));
                result.OnFileUploadCompleted += new FileUploadInfo.NotifyFileUploadCompleted(UploadCompleted);
            }
            return result;
        }
    }

FileUploadInfo.cs

    public class FileUploadInfo
{
    public delegate void NotifyFileUploadCompleted(FileUploadInfo uploadFile);
    public NotifyFileUploadCompleted OnFileUploadCompleted;
    public string UploaderName { get; private set; }
    public string FileName { get; private set; }
    public int PartsCount  { get; private set; }
    public Guid FileUploadGuid { get; private set; }
    private int _CountPartsUploaded = 0;
    private object sync_CountPartsUploaded = new object();
    public int CountPartsUploaded
    {
        private set
        {
            lock (sync_CountPartsUploaded)
                _CountPartsUploaded = value;
        }
        get
        {
            lock (sync_CountPartsUploaded)
                return _CountPartsUploaded;
        }
    }
    private bool _Fail = false;
    private object sync_Fail = new object();
    public bool Fail
    {
        get
        {
            lock (sync_Fail)
                return _Fail;
        }
        set
        {
            lock (sync_Fail)
                _Fail = value;
        }
    }
    private bool _Complete = false;
    private object sync_Complete = new object();
    public bool Complete
    {
        get
        {
            lock (sync_Complete)
                return _Complete;
        }
        set
        {
            lock (sync_Complete)
                _Complete = value;
        }
    }

    public FileUploadInfo(string UploaderName, Guid FileUploadGuid, string FileName, int PartsCount)
    {
        this.UploaderName = UploaderName;
        this.FileUploadGuid = FileUploadGuid;
        this.FileName = FileName;
        this.PartsCount = PartsCount;
    }

    public void OnAPartUploaded()
    {
        CountPartsUploaded += 1;
        if (CountPartsUploaded >= PartsCount)
        {
            OnFileUploadCompleted(this);
            Complete = true;
        }
    }
}

Client.cs

        byte[] message = new byte[2097152];
        int bytesRead;
        while (true)
        {
            bytesRead = 0;
            #region read client SPacket
            try
            {
                //blocks until a client sends a message
                /*server log*/OnNotifyMessage("[" + mstrName + "] Waiting for message");
                bytesRead = netStream.Read(message, 0, 2097152);
                if (bytesRead == 0)
                {
                    //the client has disconnected from the server
                    break;
                }
            }
            catch (Exception ex)
            {
                notifyError("Socket error", ex);
                break;
            }
            #endregion

            //message has successfully been received
            Packet pkRequestFromClient;
            Boolean bValidPacket;
            readRPacket(message, out pkRequestFromClient, out bValidPacket);
            if (bValidPacket)
            {
                processRequestPacket(pkRequestFromClient);
            }
            else
            {
                /*server log*/OnNotifyMessage("Error packet: "+ pkRequestFromClient.Exception);
            }

    private void readRPacket(byte[] data, out Packet packet, out bool bValidPacket)
    {
        try
        {
            packet = weHereConverter.DeSerializeFromByteArray<Packet>(data);
            bValidPacket = true;
        }
        catch(Exception ex)
        {
            packet = Packet.CreateErrorPacket(ex);
            bValidPacket = false;
        }
    }

Really need help..

Thanks for read!

After the line

bytesRead = netStream.Read(message, 0, 2097152);

you are not using bytesRead to determine how many bytes were received. You assume that an entire message was received. TCP gives you a stream of bytes and it does not preserve messages in any way. Your code must function even if Read decides to always read just one byte.


There is a lot of transfer logic in your code. Is it not possible to use a standardized protocol for uploading, such as HTTP, FTP, WebServices, protobuf? Socket code is very hard to get right. Best way to do it is to avoid it.

This is a race condition.

The problem is when you send (for example) a 1.2MB file, there is chance that the second 0.2MB part will be processed and written to the file BEFORE the first 1MB part.

So you can either execute all the operations on both the client- and server-sides synchronously, or (I recommend this) queue the packets on the server side, order them ascending by index and then write them in the correct order.

Tell me if you need help implementing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM