Проверка доставки сообщений TCP - PullRequest
0 голосов
/ 26 июня 2018

Я пишу приложение для отправки системных журналов на центральный сервер. Ожидается, что сетевое соединение с сервером будет ненадежным. По этой причине мне нужно иметь возможность проверить, были ли сообщения получены сервером, поэтому, если отправка не удалась, я могу попытаться отправить их снова позже.

У меня нет контроля над сервером, только возможность формировать TCP-соединение с ним - большинство вопросов, которые я видел, рекомендуют написание собственной логики ACK, но это не вариант для меня. Мне нужен полностью клиентский подход. Есть ли способ получить доступ к подтверждениям TCP, чтобы пометить сообщение как отправленное?

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace TCPClientTest
{
    class SyslogMessage
    {
        public Guid Guid = Guid.NewGuid();
        public byte[] MessageData;
    }

    class Program
    {
        static readonly int TCP_PORT = 1337;

        static byte[] SendTCPMessage(String hostname, int port, byte[] data)
        {
            using (var client = new TcpClient(hostname, port))
            {
                using (var stream = client.GetStream())
                {
                    stream.Write(data, 0, data.Length);
                    var responseData = new byte[1024];

                    var byteCount = stream.Read(responseData, 0, responseData.Length);
                    return responseData.Take(byteCount).ToArray();
                }
            }
        }

        static void SendSyslog(String hostname, int port, SyslogMessage m)
        {
            SendTCPMessage(hostname, port, m.MessageData);
        }

        static Queue<SyslogMessage> sysLogQueue = new Queue<SyslogMessage>(new List<SyslogMessage>()
        { 
            new SyslogMessage() { MessageData = Encoding.UTF8.GetBytes("Test data 1")},
            new SyslogMessage() { MessageData = Encoding.UTF8.GetBytes("Test data 2")}
        });

        static void Main(string[] args)
        {
            System.Threading.Timer timer = new System.Threading.Timer(SendLogs, null, 1000, 5000);
            Console.WriteLine("Press return to continue...");
            Console.Read();
        }

        static void SendLogs(object state)
        {
            while (sysLogQueue.Count > 0)
            {
                try
                {
                    var m = sysLogQueue.Peek();
                    SendSyslog("localhost", TCP_PORT, m);
                    Console.WriteLine("Sent sys log: " + Encoding.UTF8.GetString(m.MessageData));
                    // Remove from queue.
                    sysLogQueue.Dequeue();
                }
                catch (SocketException e)
                {
                    // Leave in the queue.
                    Console.WriteLine("Failed to send log: Socket exception occurred: {0}", e);
                    // Break until next attempt.
                    break;
                }
            }
        }
    }
}

Я использовал для этого порт 1337, просто установите для него все, что вам нужно.

0 голосов
/ 26 июня 2018

Протокол TCP гарантирует правильную доставку данных на удаленный сервер. Цитировать из оригинальной спецификации TCP в RFC 793 :

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

Таким образом, если вы не получили ошибку от отправляющей части, у вас есть подтверждение, что стек TCP удаленного сервера правильно получил ваши данные. TCP имеет встроенное обнаружение поврежденных, потерянных, дублированных или неупорядоченных доставленных пакетов (с использованием порядковых номеров) и будет повторно передавать пакеты при обнаружении проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...