Приветствую. В данный момент практикуюсь в использовании сокетов, появилась мысль сделать приложение, подобное TeamViewer'у (удаленное управление). Написал клиент и сервер, но смог реализовать только синхронную работу с сокетами.
Проблема в том, что мне нужно после подключения клиента отправить к нему запрос с сервера (например, о получении основной информации о ПК), и потом получить от него ответ. То есть, клиент должен сначала принять сообщение с сервера, дать на него ответ, и при этом остаться подключенным к серверу, чтобы в любой момент времени можно было найти этот клиент по его ID, отправить ему новый запрос и принять ответ.
Сервер реализовал через TcpListener, принимаю сообщения от клиентов следующим образом:
while (isListening)
{
try
{
TcpClient tcpClient = listener.AcceptTcpClient();
Client client = new Client(tcpClient, this);
}
catch (SocketException ex) when (ex.ErrorCode == 10004)
{
return;
}
catch (Exception ex) when (!debugMode)
{
Logger.WriteException("Socket Server", "Error: ", ex);
}
}
Отправка сообщений клиенту реализована через следующий метод в классе Client:
public byte[] SendMessage(SocketMessage socketMessage)
{
byte[] message = SocketMessage.Build(socketMessage);
NetworkStream clientStream = client.GetStream();
byte[] request = message;
clientStream.Write(request, 0, request.Length);
byte[] response = new byte[65536];
int responseLength;
do
{
responseLength = clientStream.Read(response, 0, response.Length);
}
while (clientStream.DataAvailable);
return response;
}
Собственно, этот метод вызывается в конструкторе класса, чтобы после его создания сразу отправить запрос на получение базовой информации о ПК (ОС, имя пользователя, IP адрес и т.д.)
Клиентское приложение принимает запросы и отвечает на них следующим образом:
while (true)
{
clientStream = client.GetStream();
byte[] request = new byte[1024];
int requestLength = 0;
StringBuilder requestBuilder = new StringBuilder();
requestLength = clientStream.Read(request, 0, request.Length);
Console.WriteLine("Received a request from " + client.Client.LocalEndPoint.ToString() + ", " + request.Length + " bytes");
responseMessage = ResponseToMessage(request);
Console.Write("Sending response to " + client.Client.LocalEndPoint.ToString() + ", " + responseMessage.Length + " bytes");
byte[] response = responseMessage;
clientStream.Write(response, 0, response.Length);
Console.WriteLine(" OK");
}
Но как перенести это и заставить работать асинхронно я без малейшего понятия. Пытался читать документацию, но ничего не понял. Везде примеры классической реализации, где сервер ждет запроса от клиента, и отвечает на него. Мне же нужно наоборот, отправить с сервера запрос на клиент, и получить от него ответ.