Как отправить длину пакета по протоколу tcp / ip - PullRequest
0 голосов
/ 20 апреля 2011

Я делаю это для одного из моих школьных проектов.Я пытаюсь создать многопоточный сервер, который принимает клиентов для работы с базой данных (добавление, удаление записей и т. Д.).Когда я подключаю клиента к серверу, я хочу получить всех студентов в своей базе данных.

Я получаю доступ к базе данных на стороне сервера и сохраняю информацию в ArrayList, который я пытаюсь отправить по нему.сеть.У меня нет никаких знаний о XML-сериализации, поэтому я пытаюсь отправить каждую строку в arrayList клиенту.Когда я отправляю данные с сервера, я иногда получаю все данные в одно и то же время, иногда я не получаю, поэтому мое первое предположение состояло в том, что мне нужно разделить отправляемые данные на пакеты некоторой длины.Я не вижу, как я могу добавить длину в начале пакета.Разве это не было бы то же самое?Может быть, я получаю правильную длину, а может и нет.

Вот мой код;Я еще не пытался отправить длину каждой посылки, потому что понятия не имею, как.Я пытался отправить с сервера длину массива, и много раз считывал из сетевого потока, но это не работает (я получаю все данные в одном пакете).

Сторона сервера:

private void HandleClient(object client)
    {
        try
        {
            ClientNo++;

            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();
            byte[] bytes = new byte[4096];
            int i;
            // Robot r = new Robot();
            Protocol p = new Protocol();
            ArrayList ListaStudentiResponse = p.ExecuteQueryOnStudents("select * from studenti");
            byte[] Length = new byte[4];
            Length = System.Text.Encoding.ASCII.GetBytes(ListaStudentiResponse.Count.ToString());
            clientStream.Write(Length, 0, Length.Length);
            foreach ( String s in ListaStudentiResponse)
            {

                byte[] data = System.Text.Encoding.ASCII.GetBytes(s);
                clientStream.Write(data, 0, data.Length);

            }


            tcpClient.Close();
            ClientNo--;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

На клиенте:

private void connectToServerToolStripMenuItem_Click(object sender, EventArgs e)
    {
        tcpclient = new TcpClient();

        NetworkStream netStream;
        try
        {
            tcpclient.Connect("localhost", 8181);
            netStream = tcpclient.GetStream();
            Byte[] bytes = new Byte[10000];
            int readBytes = netStream.Read(bytes, 0, bytes.Length);
             int Length  =Int32.Parse(Encoding.ASCII.GetString(bytes, 0, readBytes));
             MessageBox.Show(Length.ToString());
             int i = 0;
             while (i < Length)
             {
                i++;
                Byte[] b = new Byte[10000];
                readBytes = netStream.Read(bytes, 0, bytes.Length);
                String response = Encoding.ASCII.GetString(b, 0, readBytes);
                MessageBox.Show(response);


             }

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }
}

Ответы [ 2 ]

0 голосов
/ 20 апреля 2011

Это то, что я использовал:

Как использовать буфер на объекте SocketAsyncEventArgs

Посмотрите на принятый ответ.Во-первых, это использует какой-то порт завершения вызова, который более эффективен, чем асинхронный.Во-вторых, я обнаружил, что устранить неисправность очень просто, посмотрев на e.SocketError, чтобы узнать точную причину сбоя.

Как это работает, для отправки сообщения добавьте сообщение с заголовком и трейлером.
Поэтому, когда оно получит сообщение, оно проверит, получен ли трейлер.Если трейлер не получен, он продолжит прием для этого клиента и добавит полученное сообщение к объекту stringBuilder.Как только трейлер получен, просто вызовите stringbuilder.toString (), чтобы получить весь контент.

0 голосов
/ 20 апреля 2011

Вы можете использовать StateObject, чтобы отслеживать, насколько велики ваши данные, а затем проверять во время ReadCallback, чтобы увидеть, есть ли у вас «все» сообщения.Если у вас нет всех ваших сообщений, вы снова вызываете BeginRecieve с текущим StateObject.

Вот хороший пример: http://www.csharphelp.com/2007/02/asynchronous-server-socket-using-c/

...