V
V
Viktor2015-07-14 01:32:18
virtual box
Viktor, 2015-07-14 01:32:18

Why does a tcp connection constantly receive "garbage"?

I send the message like this:

protected TcpClient clientSocket;
       protected bool SendMessage(byte[] outStream)
        {
            try
            {
                clientStream = clientSocket.GetStream();
                clientStream.Write(outStream, 0, outStream.Length);
                clientStream.Flush();
            }
            catch
            {
                return false;
            }
            return true;
        }

I get the message like this, the class method of the client handler that came to the server.
protected bool ReceiveMessage()
        {
            int bytesRead = 0;
            try
            {
                byte[] header = new byte[4];
                bytesRead = clientStream.Read(header, 0, 4);
                if (bytesRead != 0)
                {
                    MemoryStream ms = new MemoryStream(header);
                    BinaryReader br = new BinaryReader(ms);
                    int messageLength = br.ReadInt32();
                    br.Close();
                    bytesRead = 0;
                    receiveMessage = new byte[messageLength];
                    bytesRead = clientStream.Read(receiveMessage, 0, messageLength);
                }
            }
            catch
            {
                //a socket error has occured
                return false;
            }
            if (bytesRead == 0)
            {
                //the client has disconnected from the server
                return false;
            }
            return true;
        }

The first 4 bytes are the size of the data, then the data itself. I subtract how much the size was transferred. Variable length packet.
The next step is parsing the message.
When tracing the Server and Client code. Data arrives correctly from one virtual machine to another. But if you "leave free swimming" i.e. run them for execution without any BreakPoints, then an error occurs on the line receiveMessage = new byte[messageLength]; Either Arithmetic error or OutMemoryException.
So, for some reason, the messageLength variable takes that negative (most often the same) value, and sometimes a positive value. And modulo this value is very huge. At the same time, exactly messageLength is available for reading in the socket, if it were correctly read. It turns out that the information comes, but garbage (and always the same).
Two machines under VirtualBox 4.2.28, tried on the younger, older. All one. Host OS Ubuntu 12.04.5.
The machines have two network ones, one as NAT, the second Host-Only.
UPDATE:
I form outStream like this:
byte[] outStream;
            using (MemoryStream mstream = new MemoryStream())
            {
                // Sending portion of File
                BinaryWriter bw = new BinaryWriter(mstream);
                bw.Write(12);                     //Command
//Вместо коментария пишем еще данных с помощью bw
                bw.Flush();
                int messageLength = (int)bw.BaseStream.Length;
                MemoryStream msOut = new MemoryStream();
                BinaryWriter bwOut = new BinaryWriter(msOut);
                bwOut.Write(messageLength);
                bwOut.Flush();
                mstream.WriteTo(msOut);
                outStream = msOut.ToArray();
                bwOut.Close();
            }

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vitaly Pukhov, 2015-07-14
@JmAbuDabi

You can read the data while it is there, as much as it is, it is not necessary to know its length. Working example (not for the console, but does not change the essence)

namespace TCP_Server
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            MethodInvoker mi = new MethodInvoker(delegate
            {
                int port = 999; //взяли порт из файла
                TcpListener l = new TcpListener(port); //и на нем у нас висит сервер
                l.Start(); //запущен
                while (true)
                {
                    TcpClient cl = l.AcceptTcpClient();
                    Connection c = new Connection();
                    c.cl = cl;
                    Thread t = new Thread(new ThreadStart(c.Work));
                    t.IsBackground = false;
                    t.Start();
                }
            });
            mi.BeginInvoke(null, null);
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        public class Connection
        {
            public TcpClient cl;
            public void Work()
            {
                NetworkStream NWS = cl.GetStream();
                //BinaryReader R = new BinaryReader(NWS); //принятие
                //BinaryWriter W = new BinaryWriter(NWS); //отправка
                if (NWS.CanRead)
                {
                    StringBuilder fullServerReply = new StringBuilder();
                    byte[] readBuffer = new byte[cl.ReceiveBufferSize];
                    int numberOfBytesRead = 0;
                    do
                    {
                        numberOfBytesRead = NWS.Read(readBuffer, 0, readBuffer.Length);
                        fullServerReply.AppendFormat("{0}", Encoding.UTF8.GetString(readBuffer, 0, cl.ReceiveBufferSize));
                    } while (NWS.DataAvailable);
                    var s = fullServerReply.ToString();
                    Console.WriteLine(s); // тут твои данные
                }
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TCP_Client
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public int port = 999; //умолчание
        public string adres = "127.0.0.1"; //умолчание
        NetworkStream NWS;
        BinaryReader R;
        BinaryWriter W;
        private void Form1_Load(object sender, EventArgs e)
        {
            reg();
        }

        private void reg()
        {
            //создадим сокетное подключение для общения с сервером
            TcpClient client = new TcpClient(adres, port); //IP адрес сервера и порт на котором он висит
            NWS = client.GetStream();
            R = new BinaryReader(NWS); //поток для принятия данных
            W = new BinaryWriter(NWS); //поток для отправки данных

            //ну и тут ваше что-то
        }

        static byte[] GetBytes(string str)
        {
            byte[] bytes = new byte[str.Length * sizeof(char)];
            System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
            return bytes;
        }

        static string GetString(byte[] bytes)
        {
            char[] chars = new char[bytes.Length / sizeof(char)];
            System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
            return new string(chars);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            reg();
            W.Write(textBox1.Text);
            NWS.Flush();
        }
    }
}

The data could be packed into a class along with the check sum and sent after serialization, at the same time it could also be compressed (so that you have to transfer less), here is an example of implementing serialization with compression:
string FileName = "Signes.db";
        public void Save()
        {
            //Сохраняем резервную копию
            if (File.Exists(FileName))
            {
                File.Copy(FileName, FileName + DateTime.Now.ToShortDateString() + ".bak", true);
            }
            BinaryFormatter bf = new BinaryFormatter();
            //откроем поток для записи в файл
            using (FileStream fs = new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
            using (GZipStream gz = new GZipStream(fs, CompressionMode.Compress, false))
            {
                bf.Serialize(gz, Signes);//сериализация
            }
        }
        public void Load()
        {
            if (!File.Exists(FileName))
            {
                Signes = new List<BaseSign>(); //указать тип нового объекта
                Save();
            }
            BinaryFormatter bf = new BinaryFormatter();
            using (FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (GZipStream gz = new GZipStream(fs, CompressionMode.Decompress, false))
            {
                Signes = (List<BaseSign>)bf.Deserialize(gz); //указать тип объекта
            }
        }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question