#c# #sockets #tcp #uwp
#c# #сокеты #tcp #uwp
Вопрос:
Итак, я хочу установить TCP-соединение между 2 приложениями UWP, используя streamsockets. Я нашел этот пример на веб-странице Microsoft, и он работает. Проблема в том, что он закрывает свои сокеты после каждого установленного соединения. Я хочу понять, когда он закрывается (не могу найти его в коде, и это меня немного смущает), и я также хочу знать, как я мог бы поддерживать соединение между сервером и клиентом открытым, чтобы мне не приходилось переподключаться каждый раз, когда я хочу что-то отправить.
Я просмотрел документацию StreamSocket в Windows и не могу найти ничего о закрытии сокета.
Я предполагаю, что это происходит где-то в этом методе. Это серверная часть программы, которая выполняется при получении соединения.
private async void StreamSocketListener_ConnectionReceived
(Windows.Networking.Sockets.StreamSocketListener sender,
Windows.Networking.Sockets.
StreamSocketListenerConnectionReceivedEventArgs args)
{
string request;
using (var streamReader = new
StreamReader(args.Socket.InputStream.AsStreamForRead()))
{
request = await streamReader.ReadLineAsync();
}
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add(string.Format("server received the request: "{0}"", request)));
// Echo the request back as the response.
using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(request);
await streamWriter.FlushAsync();
}
}
string request;
using (var streamReader = new
StreamReader(args.Socket.InputStream.AsStreamForRead()))
{
request = await streamReader.ReadLineAsync();
}
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
this.serverListBox.Items.Add(string.Format("server received the
request: "{0}"", request)));
// Echo the request back as the response.
using (Stream outputStream =
args.Socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(request);
await streamWriter.FlushAsync();
}
}
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
this.serverListBox.Items.Add(string.Format("server sent back the
response: "{0}"", request)));
sender.Dispose();
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
this.serverListBox.Items.Add("server closed its socket"));
}
Любая помощь будет очень признательна!
Ответ №1:
Я нашел этот пример на веб-странице Microsoft, и он работает.
К сожалению, все примеры сокетов Microsoft не являются хорошими примерами того, как писать приложения для сокетов. Это всего лишь примеры того, как вызывать эти API. Создание приложения для сокетов производственного качества нетривиально, и примеры сокетов Microsoft введут вас в заблуждение.
Например, этот сервер сокетов:
- Используется
Dispatcher
для обновления пользовательского интерфейса, а не для современных решений, таких какIProgress<T>
. - Считывает данные из своего входного потока до тех пор, пока не будет найдена новая строка. Это проблема, потому что:
- Для получения запроса нет времени ожидания.
- Входной буфер растет без ограничений.
- Сценарий полуоткрытия не обрабатывается.
Большинство примеров сокетов от Microsoft имеют те же проблемы, все из которых должны быть решены при написании кода сокета производственного качества. И написать код сокета производственного качества намного сложнее, чем кажется на первый взгляд.
По этой причине я всегда рекомендую использовать альтернативную технологию (например, автономный SignalR), если это возможно.
Но чтобы ответить на ваш фактический вопрос:
Я хочу понять, когда он закрывается
С сокетами фактически существует два потока: входной поток и выходной поток. Оба закрываются при sender.Dispose();
вызове. Однако входной поток также закрывается при StreamReader
удалении, а выходной поток также закрывается при StreamWriter
удалении. Это происходит в конце их using
блоков. Вот почему вы не можете прочитать второе сообщение после закрытия StreamReader
.
Комментарии:
1. Спасибо за ответ! Теперь я немного лучше понимаю код.
2. Я собираюсь изучить SignalR, потому что мне действительно нравится изучать сокеты