Answer the question
In order to leave comments, you need to log in
How to implement asynchronous socket reception in C#?
Greetings. At the moment I'm practicing using sockets, I had an idea to make an application similar to TeamViewer (remote control). I wrote a client and a server, but I could only implement synchronous work with sockets.
The problem is that after connecting the client, I need to send a request to it from the server (for example, about obtaining basic information about the PC), and then receive a response from it. That is, the client must first receive a message from the server, give a response to it, and at the same time remain connected to the server so that at any time you can find this client by its ID, send it a new request and receive a response.
The server implemented through TcpListener, I receive messages from clients as follows:
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);
}
}
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;
}
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");
}
Answer the question
In order to leave comments, you need to log in
I tried to read the documentation, but did not understand anything. Everywhere examples of classical implementation, where the server waits for a request from the client, and responds to it. On the contrary, I need to send a request from the server to the client, and receive a response from it.
// один раз инициализировали
var tcpListener = new TcpListener(IPAddress.Any, 8090);
tcpListener.Start();
tcpListener.BeginAcceptTcpClient(OnAcceptTCPClient, null); // Начали ждать коннектов
// На коннект клиента
private void OnAcceptTCPClient(IAsyncResult ar)
{
var client = tcpListener.EndAcceptTcpClient(ar);
new ClientReceiver(client); // Здесь будем асинхронно получать данные от клиентов.
lock (clients)
clients.Add(client); // сохранили для отправок
// начинаем ждать новых коннектов
tcpListener.BeginAcceptTcpClient(OnAcceptTCPClient, null);
}
ClientReceiver(TcpClient tcpClient) {
buffer = new byte[READ_BUFFER_SIZE];
stream = tcpClient.GetStream();
asyncResult = stream.BeginRead(buffer, 0, READ_BUFFER_SIZE, ReadStreamCallback, null);
}
// когда данные пришли
private void ReadStreamCallback(IAsyncResult ar)
{
int readed;
readed = stream.EndRead(ar);
AddData(buffer, readed); // обрабатываем, что получили
// запускаем новое ожидание
asyncResult = stream.BeginRead(buffer, 0, READ_BUFFER_SIZE, ReadStreamCallback, null);
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question