Я предполагаю, что здесь есть какие-то розетки. Я подозреваю, что реализация Java просто закрывает клиентский сокет, возможно, вызывая ошибку на сервере, в то время как версия C # немного более дружественна к серверу и ожидает, пока он подтвердит закрытый запрос. Поскольку сервер занят отправкой данных, он не получает (или, по крайней мере, не обрабатывает) запрос на закрытие, пока не завершит отправку.
Подумайте об этом так: кто-то за вашей дверью пытается вам что-то продать, и вас не прервут. Вы можете хлопнуть дверью по их лицу, которое немедленно закрывает их, или можете подождать, пока они закончат разговор, и затем попросить их уйти.
Чтобы решить эту проблему, возможно, вы могли бы создать рабочий поток, который открывает поток, ждет 100 байт, а затем закрывается. В то же время ваша программа может делать все, что ей нужно, в то время как поток в конечном итоге закрывается.