#c# #.net #multithreading #network-programming #threadpool
Вопрос:
Я пишу клиент TCP/IP для одновременной отправки и получения данных на подключенный хост. Мой подход заключается в подключении к конечной точке и использовании сокета.Подключенное свойство для цикла между получением и отправкой, если есть какие-либо данные для отправки. Все методы синхронизированы с блокировкой на месте для чтения данных из потока. Есть ли что-то неправильное в том, чтобы вызывать BeginReceieve несколько раз в цикле? Наблюдая за тем, как это выполняется через пул потоков, управляет ли базовая среда выполнения количеством потоков, буферизованных для каждого вызова, или я должен стремиться контролировать, когда я вызываю begin receive в указанном цикле while?
Комментарии:
1. Я думаю, что лучше всего вызвать BeginRecive() в цикле. Я не знаю, зачем вам нужен цикл while, потому что BeginRevice() нужен метод обратного вызова, и всякий раз, когда клиент/сервер отправляет обновление, он автоматически вызывает метод обратного вызова с результатами
2. Привет @Тайсон, я делаю петлю, чтобы позволить мне продолжать прием, пока розетка подключена. и далее после настроенного ожидания я могу искать данные для отправки. Это, по сути, будет повторяться до тех пор, пока связь будет хорошей. Является ли ваша мысль о том, что потоки BeginRecieve() будут закрыты пулом потоков через некоторое время после того, как вы фактически не получите никаких данных от подключенного хоста?
Ответ №1:
Вам не нужен цикл, когда вы вызываете BeginRecive(). BeginRecive () — это асинхронный метод, и когда вы пишете _socket.BeginRecive() Начинает асинхронно получать данные от подключенного сокета/клиента.
например:
public static void SetupRegisterServer() { Console.WriteLine("Setting up the Messesing Server!"); _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 102)); _serverSocket.Listen(5); //Backlog is pending conditions can exists. _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); //Async method BeginAccept if any client connect it will call the AcceptCallback method Console.WriteLine("Messesing Server running......"); }
Функция обратного вызова AcceptCallback
public static void AcceptCallback(IAsyncResult ar) { var socket = _serverSocket.EndAccept(ar);//End accept Console.WriteLine("Client Connect To Messesings Server"); _clientSocketList.Add(socket);// add client to list // Start reciving from the connected client with callback function ReciveCallback socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReciveCallback), socket); _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); //Here we again accepting clients. }
Способ обратного вызова
private static void ReciveCallback(IAsyncResult ar) { //here you will get the socket of the clint which send the data Socket socket = (Socket)ar.AsyncState; int recived = socket.EndReceive(ar);//recive == data.length byte[] dataBuffer = new byte[recived]; Array.Copy(_buffer, dataBuffer, recived); //Data send from client string decodedText = Encoding.ASCII.GetString(dataBuffer); //Start receiving again from the same client socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReciveCallback), socket); }
Вы также можете использовать сокет.BeginSend() для отправки данных при получении обратного вызова
Комментарии:
1. Спасибо за хорошо иллюстрированный ответ @Tyson . В моем сценарии я создаю клиента, поэтому вместо прослушивания я определяю сокет и вызываю BeginConnect. Предполагая, что мое соединение успешно, я могу, по сути, просто вызвать BeginRecieve() в соответствии с вашим методом обратного вызова для чтения, однако, если предположить, что эти методы вызываются в основном методе, не завершится ли выполнение, как только мы достигнем последней строки в указанном методе, который будет эффективно завершать прием до тех пор, пока не будет запущена служба/приложение?