Во-первых, вы должны проверить детали получаемых вами исключений SocketException. Я не знаю, что они содержат в .Net, но в Java подробное сообщение содержит полезную подсказку, такую как «Соединение закрыто одноранговым узлом» или «Сброс соединения».
По моему опыту, частой причиной разрыва соединений с сокетом является ошибка в коде, когда исключение тайм-аута чтения обрабатывается тем же условием catch, что и все другие исключения, связанные с соединением, что обычно приводит к закрытию соединения для нет веской причины.
В корпоративных установках типичной причиной закрытия длительных TCP-соединений является устройство брандмауэра, которое закрывает TCP-соединения без трафика, скажем, через 10 минут, или закрывает соединения после того, как их возраст достигает, скажем, 30 минут, независимо от того, трафика. В общем, лучше предположить, что такие вещи произойдут, и быть готовым восстановить соединение изящно.
Хороший подход - это посмотреть, есть ли шаблон в соединителях соединений. Например, закрываются ли они периодически или после определенного времени бездействия. Вы также можете запустить анализатор пакетов, чтобы узнать, какая сторона инициирует отключение соединения или отправляет пакет RST и почему.