При написании клиент-серверной программы и ранее использовались такие вызовы:
TcpListener.AcceptTcpClient()
NetworkStream.Read()
NetworkStream.Write()
TcpListener.AcceptTcpClient()
работает нормально, потому что его функция обратного вызова тольковызывается после установления соединения.
Однако BeginRead()
также не работает.По какой-то причине он выполняется и продолжается после него, даже если данные не отправляются. Не уверен, что происходит.NetworkStream.Read()
блокировал просто отлично, но это не так.
Вот нерабочий поток, который создается при каждом установлении соединения:
private void HandleClientCommunication(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
try
{
byte[] header = new byte[4];
clientStream.BeginRead(header, 0, header.Length, Read, new StateData(clientStream, header)); // Runs even if no data is sent
int dataLength = BitConverter.ToInt32(header, 0); // Continues to this, even if no packets are sent..
byte[] data = new byte[dataLength]; // dataLength is 0 still of course because none of the code is blocking
clientStream.BeginRead(data, 0, dataLength, Read, new StateData(clientStream, data));
}
catch (IOException e)
{
Console.WriteLine(e.InnerException.Message);
}
// not relevant past here
}
Вот и метод Read,Не уверен, если это необходимо, чтобы выяснить проблему, но я включу ее независимо от того:
private void Read(IAsyncResult async)
{
StateData stateData = (StateData)async.AsyncState;
stateData.BytesRead += stateData.Stream.EndRead(async);
if (stateData.BytesRead < stateData.Bytes.Length)
{
stateData.Stream.BeginRead(stateData.Bytes, 0, stateData.Bytes.Length, Read, stateData);
}
else
{
string message = Encoding.ASCII.GetString(stateData.Bytes);
Console.WriteLine(message);
}
}
Так что да, я просто пытаюсь настроить взаимодействие клиент-сервер с асинхронными вызовами и иметь каждый «пакет»включите заголовок с длиной данных как int, а затем сразу после этого сами данные.К сожалению, кажется, что все не работает, и я не уверен, в чем проблема.
Похоже, мне нужно включить некоторую ручную форму блокировки, но разве это не противоречит цели использования асинхронных вызовов?Почему бы тогда просто не вернуться к обычным синхронным вызовам блокировки, таким как Read()
и AcceptTcpClient()
в этот момент?
Не думаю, что здесь я полностью понимаю вещи ..