У меня серьезная проблема с полуприкрытием TcpClient. То, что я пытаюсь сделать, это:Half-закрытие TcpClient
На клиенте:
- Отправить сообщение
- Shutdown основной разъем для отправки
- Получить ответ
- Shutdown основной разъем для чтения (или, на данный момент, просто закройте его)
На сервере:
- Получить сообщение
- Shutdown основной разъем для чтения
- отправить ответ
- Shutdown основной разъем для записи (или, в этот момент, просто закройте его)
Однако , после шага 2 на клиенте или на сервере я не могу использовать поток TcpClient. Вот очень упрощенный вариант моего кода (без асинхронных вызовов, обработки и очистки, а также с помощью StreamReader и StreamWriter вместо XmlSerializer):
//initialize the connection between the server and the client
var listener = new TcpListener(IPAddress.Any, 13546);
listener.Start();
var client = new TcpClient("127.0.0.1", 13546);
var server = listener.AcceptTcpClient();
listener.Stop();
//CLIENT: send the message
var cwriter = new StreamWriter(client.GetStream());
cwriter.Write("client's message");
cwriter.Flush();
client.Client.Shutdown(SocketShutdown.Send);
//SERVER: receive the message
string msg;
var sreader = new StreamReader(server.GetStream());
msg = sreader.ReadToEnd();
server.Client.Shutdown(SocketShutdown.Receive);
//SERVER: send a response
//Here the code fails on server.GetStream() -
//InvalidOperationException, apparently the whole connection is closed now
var swriter = new StreamWriter(server.GetStream());
swriter.Write(msg + " with server's response");
swriter.Flush();
server.Client.Shutdown(SocketShutdown.Send);
//CLIENT: receive the message
var creader = new StreamReader(client.GetStream());
var response = creader.ReadToEnd();
client.Client.Shutdown(SocketShutdown.Receive);
Есть ли способ сделать это без использования сокеты ? Я что-то не понимаю?
Что означает отказ? Переход к сырым сокетам кажется преждевременным и произвольным. Скорее, исправить ошибку, и вы хороши. – usr
'StreamWriter' берет на себя ответственность за переданный ему поток. Когда он собирает мусор, основной поток также удаляется. Вы бы четко это заметили, если бы вы разместили «StreamWriter», как и предполагалось (что означает «IDisposable»). Вы можете использовать перегрузку конструктора, которая оставляет поток открытым. В качестве альтернативы, не беспокойтесь ни о чем из этого - если вам нужно получить доступ к базовому сокету 'TcpClient', вы обычно делаете это неправильно. Сокет действительно не нужно отключать вручную с помощью логики прерывания. –
@JeroenMostert хороший улов, но проблема не должна легко проявляться. Есть ли у SR даже финализатор? Это не должно. Кроме того, выключение может сигнализировать о завершении потока на удаленную сторону. Я думаю, что закрытие приема не делает много, да. – usr