Transfer of Socket Files c#

Asked

Viewed 682 times

1

I have the following situation, I need to transfer an xml from one application to another via network (Socket) set up the methods of client and server which I will post just below, The file is transmitted smoothly, however files with more than 6kb are coming incomplete, I have been researching some methods on the network but so far none teaches me exactly how to ensure the integrity of the file, This is that the file was received completely. There is another problem in the method below this catching on While, Until I give the client.close does not leave, However I needed to send the return to the customer if I close the connection can not, Follow code:

Client:

try
            {
                //Grava o arquivo fisico
                var savedFile = Auxiliares.SalvarArquivo(xml, vendaid, "xml");
                //Pega o nome do arquivo
                var nomeArquivo = savedFile[1];

                //Valida o tamanho
                var nomeArquivoByte = Encoding.UTF8.GetBytes(nomeArquivo);
                if (nomeArquivoByte.Length > 5000 * 1024)
                {
                    return "O tamanho do arquivo é maior que 5Mb, tente um arquivo menor.";
                }

                //Sepera os bytes e etc
                var fileData = Auxiliares.ReadAllBytes(savedFile[2]);
                var clientData = new byte[4 + nomeArquivoByte.Length + fileData.Length];
                var nomeArquivoLen = BitConverter.GetBytes(nomeArquivoByte.Length);

                //Copia para o stream
                nomeArquivoLen.CopyTo(clientData, 0);
                nomeArquivoByte.CopyTo(clientData, 4);
                fileData.CopyTo(clientData, 4 + nomeArquivoByte.Length);

                //Conecta
                clientSock.Connect(ipEnd);

                //Envia
                clientSock.Send(clientData, 0, clientData.Length, 0);

                //Recebe o retorno do servidor
                clientSock.Receive(retornoServidorByte);

                //Fecha conexao
                clientSock.Close();

            }
            catch (SocketException soc)
            {
                return soc.Message;
            }

Server:

//Aceita a conexao
                    using (Socket clientSock = sock.Accept())
                    {

                        WriteLog("Cliente: " + clientSock.RemoteEndPoint + " Conectado");

                        #region NEW
                        //Buffer
                        clientSock.ReceiveBufferSize = 16384;

                        //Tamanho buffer arquivo
                        var dadosCliente = new byte[1024 * 50000];

                        //Recebe os dados enviados do cliente
                        var tamanhoBytesRecebidos = clientSock.Receive(dadosCliente, dadosCliente.Length, 0);
                        //Tamanho arquivo
                        var tamnhoNomeArquivo = BitConverter.ToInt32(dadosCliente, 0);
                        //Nome Arquivo
                        var nomeArquivo = Encoding.UTF8.GetString(dadosCliente, 4, tamnhoNomeArquivo);

                        //Caminho para salvar o arquivo
                        var caminhoRecepcaoArquivos = Application.StartupPath + @"\tempfiles\";
                        if (!Directory.Exists(caminhoRecepcaoArquivos))
                            Directory.CreateDirectory(caminhoRecepcaoArquivos);

                        //Escreve os dados recebidos no arquivo
                        var bWrite = new BinaryWriter(File.Open(caminhoRecepcaoArquivos + nomeArquivo, FileMode.Append));
                        bWrite.Write(dadosCliente, 4 + tamnhoNomeArquivo, tamanhoBytesRecebidos - 4 - tamnhoNomeArquivo);

                        //Valida o Recebimento (AQUI TRAVA ENQUANTO NAO DER CLOSE NO CLIENTE)
                        while (tamanhoBytesRecebidos > 0)
                        {
                            tamanhoBytesRecebidos = clientSock.Receive(dadosCliente, dadosCliente.Length, 0);
                            if (tamanhoBytesRecebidos == 0)
                            {
                                bWrite.Close();
                            }
                            else
                            {
                                bWrite.Write(dadosCliente, 0, tamanhoBytesRecebidos);
                            }
                        }
                        bWrite.Close();

                        //Monta o arquivo em memoria
                        string xml = Encoding.UTF8.GetString(File.ReadAllBytes(caminhoRecepcaoArquivos + nomeArquivo)).Replace("\0", string.Empty);

                        //Pega o retorno do SAT e envia devolta ao cliente
                        byte[] arquivoRetorno = Encoding.UTF8.GetBytes(retorno);

                        //Aqui eu devolveria um RETORNO PARA O CLIENTE POREM
                        clientSock.Send(arquivoRetorno);

                        //Fecha a conexao
                        clientSock.Close();
}

You need a way to ensure that the file arrives complete and I need to return a message to the client informing the result of the processing that would be a XML, Summarizing the flow: Client sends xml to server > Server reads file and processes > Returns client response xml

  • gives a search on Minimal Lower Layer Protocol (MLLP) that defines the message start and end characters.

2 answers

1


I got it this way, I do not know if it would be the most correct but it was the only one that solved the problem, as the problem were files that exceeded 6kbs me instead of sending the whole file, I broke it into "Packages" of 6kbs and on sent separately, At the end I unite the parts and the file arrives 100%, Follows:

CLIENT:

//Coneta com o Cliente
                clientSock.Connect(ipEnd);

                #region ENVIO
                //Pega o tamanho total do arquivo e envia para o servidor
                var tamanho = Encoding.UTF8.GetBytes(xml.Length.ToString());

                //Envia o tamanho do arquivo ao servidor
                clientSock.Send(tamanho);

                //Aguarda a confirmação de recebimento
                clientSock.Receive(new byte[1024*5000]);

                //Indice inicial do substring
                var startIndex = 0;

                //Total restante a ser enviado
                var restante = xml.Length;

                //Envia os pacotes
                while (restante > 0)
                {
                    //Se o restante for maior que 6kbs
                    if (restante > 6144)
                    {
                        //Quebra a string em 6kb
                        var pacote = xml.Substring(startIndex, 6144);

                        //Incrementa o indice do substring
                        startIndex += 6144;

                        //Abate do restante ja enviado
                        restante = restante - pacote.Length;

                        //Envia o pacote
                        clientSock.Send(Encoding.UTF8.GetBytes(pacote));

                        //Recebe resposta confirmação
                        clientSock.Receive(new byte[1024*5000]);
                    }
                    else
                    {
                        //Pega o restante ou total se arquivo menor que 6kbs
                        var pacote = xml.Substring(startIndex, restante);
                        //Abate do restante
                        restante = restante - pacote.Length;
                        //Envia o pacote
                        clientSock.Send(Encoding.UTF8.GetBytes(pacote));
                        //Recebe resposta confirmação
                        clientSock.Receive(new byte[1024 * 5000]);
                    }
                }

SERVER:

using (Socket clientSock = sock.Accept())
                            {

                                //Buffer de recebimento
                             byte[] clientData = new byte[1024*5000];

                            //Recebe o tamanho total esperado
                            clientSock.Receive(clientData);

                            WriteLog("Recebendo dados cliente...");

                            //Retorna confirmação de recebimento
                            clientSock.Send(Encoding.UTF8.GetBytes("true"));

                            //Recebe o tamanho total do arquivo que esta sendo recebido
                            var tamanho = int.Parse(Encoding.UTF8.GetString(clientData).Replace("\0", string.Empty));

                            //Arquivo xml para armazenar os pacotes ja em string
                            var xml = "";

                            //Recebe os dados e monta o xml
                            while (tamanho > 0)
                            {
                                //Recebe o pacote
                                var pacote = clientSock.Receive(clientData);

                                //Incrementa na string (Uni os pacotes) o valore recebido
                                xml += Encoding.UTF8.GetString(clientData).Replace("\0", string.Empty);

                                //Abate do total ja recebido
                                tamanho -= pacote;

                                //Limpa o buffer
                                clientData = new byte[1024*5000];

                                //Envia ao cliente a confirmação de recebimento
                                clientSock.Send(Encoding.UTF8.GetBytes("true"));
                            }
   }

Tested uploading file with more than 1mb and worked perfectly.

1

I have something similar, but the information is different. I use MLLP to transfer the files completely. Follow the implementation:

public class SiMLLP
{
    private static byte[] StartBlock = new byte[] { 0x0B };
    private static byte[] EndBlock = new byte[] { 0x1C, 0x0D };
    private static byte[] ACK = new byte[] { 0x0B, 0x06, 0x1C, 0x0D };
    private static byte[] NAK = new byte[] { 0x0B, 0x15, 0x1C, 0x0D };

    private Stream _stream;
    private bool _version3;

    public SiMLLP(Stream stream, bool version3)
    {
        _stream = stream;
        _version3 = version3;
    }

    public bool Send(string message)
    {
        byte[] bytes = Encoding.ASCII.GetBytes(message);
        _stream.Write(StartBlock, 0, StartBlock.Length);
        _stream.Write(bytes, 0, bytes.Length);
        _stream.Write(EndBlock, 0, EndBlock.Length);
        _stream.Flush();
        if (_version3)
        {
            byte[] rsp = new byte[4];
            if (_stream.Read(rsp, 0, 4) != 4)
                return false;
            return rsp[1] == 0x06;
        }
        return true;
    }

    public string Receive()
    {
        int ib = 0x00;
        MemoryStream ms = new MemoryStream();
        for (; _stream.ReadByte() != 0x0B; ) ;
        while (true)
        {
            if (ib == 0x1C)
            {
                ib = _stream.ReadByte();
                if (ib == 0x0D)
                    break;
                ms.WriteByte(0x1C);
                ms.WriteByte((byte)ib);
            }
            else
            {
                ib = _stream.ReadByte();
                if (ib != 0x1C)
                    ms.WriteByte((byte)ib);
            }
        }
        if (_version3)
        {
            _stream.Write(ACK, 0, ACK.Length);
            _stream.Flush();
        }
        return Encoding.ASCII.GetString(ms.ToArray());
    }
}

Utilizing:

        NetworkStream _stream = this.TCPClient.GetStream();
        SiMLLP mllp = new SiMLLP(_stream, false);
        //Enquanto a flag _running estiver como true, e o client conectado
        while (_running && this.TCPClient.Connected)
        {
            try
            {
                if (_stream.DataAvailable)
                {
                    //Aqui será retornada a mensagem completa, independente do tamanho dela
                    string msgRecebida = mllp.Receive();

                    if (!String.IsNullOrEmpty(msgRecebida))
                    {
                       //Processa a mensagem

                       //Aqui envio qualquer mensagem de retorno
                       mllp.Send("ACK");
                    }
                 }
                 ...
              }
              catch{}
              ...
        }
  • I tried to adapt this form in my but unsuccessfully, In the socket I could not use the Getstream would have to be Tcpclient, I managed to do otherwise , I will post below may be useful

  • Thank you for the force

  • No problems, congratulations on the solution

Browser other questions tagged

You are not signed in. Login or sign up in order to post.