Здравствуйте!
Пишу программу для обмена файлами на языке C# используя протокол TCP и сокеты. Знаю, что этот протокол обеспечивает надёжную и упорядоченную доставку данных. Но можно ли полагаться на него полностью, в плане того, что полученные данные не содержат ошибок возникших при передаче? Вот цитата из Вики:
Хотя протокол осуществляет проверку контрольной суммы по каждому сегменту, используемый алгоритм считается слабым. (...) В общем случае распределенным сетевым приложениям рекомендуется использовать дополнительные программные средства для гарантирования целостности передаваемой информации.
Если при передаче действительно возможны ошибки, то вот как я предполагаю их обойти. В моей программе есть класс NetMessage, инкапсулирующий логику отправки и получения данных. Он содержит экземпляр структуры Header - заголовок, в самом простом случае это длина данных и код команды; и, собственно, сами данные - байтовый массив. Вот так происходит отправка данных:
public async Task ReceiveAsync()
{
await header.ReceiveAsync(netHelper); //Получаю заголовок.
if (header.LengthData != -1)
buffer = await netHelper.ReceiveAsync(header.LengthData); //Если в сообщении есть данные, то получаю их.
}
Если предположить, что при передаче возможны ошибки, то и после получения заголовка, и после получения данных необходимо отсылать уведомления о том, что данные получены успешно или нет. Выглядеть это может примерно так:
public async Task ReceiveAsync()
{
const byte SUCCESS = 1;
const byte FAILURE = 2;
if (await header.ReceiveAsync(netHelper))
await netHelper.SendAsync(new byte[1] { SUCCESS });
else
await netHelper.SendAsync(new byte[1] { FAILURE });
if (header.LengthData != -1)
{
buffer = await netHelper.ReceiveAsync(header.LengthData);
if (CheckHash(buffer, header.Hash))
await netHelper.SendAsync(new byte[1] { SUCCESS });
else
await netHelper.SendAsync(new byte[1] { FAILURE });
}
}
Выглядит неплохо, но только теперь на каждую отправку данных кроме двух вызовов метода ReceiveAsync для отправки данных, ещё добавятся два вызова метода SendAsync для отправки уведомлений, и соответственно, два вызова ReceiveAsync на принимающей стороне для их получения в аналогичном методе SendAsync класса NetMessage. Эти лишние вызовы повлияют и на скорость передачи данных и увеличат нагрузку на канал связи, особенно если их будет много (при передаче большого файла, например. Он будет разделён на части, допустим по 8 кб, и каждая эта часть будет передана с помощью NetMessage).
Вопрос в том, нужно ли это всё делать? Действительно ли возможны ошибки? И если возможны, то нужно использовать тот подход, который я предложил, или можно сделать иначе и сэкономить на сетевых операциях?
Спасибо за внимание.