Проблема корректного завершения работы .NETCF Async TCP socket

У меня есть клиент-серверное приложение TCP для связи с устройством Windows CE через соединение ActiveSync. И клиент, и сервер используют асинхронные сокеты (то есть функции Socket.Begin* и Socket.End*). Когда и клиент, и сервер работают на моем рабочем столе, все работает точно так, как ожидалось, но когда клиент работает на устройстве Windows CE, подключенном через ActiveSync, я всегда получаю SocketException в ReceiveCallback после вызова Socket.Shutdown (когда устройство инициирует разъединение). Полное исключение:

System.Net.Sockets.SocketException: An error message cannot be displayed because an optional resource assembly containing it cannot be found
at System.Net.Sockets.Socket.ReceiveNoCheck()
at ReceiveAsyncRequest.doRequest()
at AsyncRequest.handleRequest()
at WorkerThread.doWork()
at WorkerThread.doWorkI()
at WorkItem.doWork()
at System.Threading.Timer.ring()

Все также работает правильно, если сервер (работающий на рабочем столе) инициирует отключение. У меня есть пара идей, как этого избежать, в том числе запрет на отключение, инициированное устройством, и игнорирование всех исключений после инициирования отключения. Тем не менее, я хотел бы знать, почему это происходит и есть ли лучший способ справиться с этим.

Disconnect и ReceiveCallbacks (функционально идентичные как на сервере, так и на клиенте):

public bool Disconnect(StateObject state)
{
  try{
    if(state.isDisconnecting) return false;

    state.isDisconnecting = true;
    state.sock.Shutdown(SocketShutdown.Both);
    //Wait for sending and receiving to complete, but don't wait more than 10 seconds
    for(int i=0; i<100 && (state.isSending || state.isReceiving); i++){
      System.Threading.Thread.Sleep(100);
    }

    /* Log the disconnect */

    state.sock.Close();

    return true;
  } catch (Exception e){
    /* Log the exception */

    return false;
  }
}

private void ReceiveCallback(IAsyncResult iar)
{
  StateObject state = (StateObject)iar.AsyncState;
  try{
    //handle the new bytes in the buffer.
    int recv = state.sock.EndReceive(iar);

    //Handle the buffer, storing it somewhere and verifying complete messages.

    if(recv > 0){
      //start listening for the next message
      state.sock.BeginReceive(state.recvBuffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
    } else {
      state.isReceiving = false;
      Disconnect(state);
    }
  } catch (Exception e){
    /* Log the exception */
  }
}

//For reference, A StateObject looks kinda like this:
public class StateObject
{
  public const int BUFFER_SIZE = 1024;

  public Socket sock = null;
  public bool isSending = false;
  public bool isReceiving = false;
  public bool isDisconnecting = false;

  public byte[] recvBuffer = new byte[BUFFER_SIZE];
  public byte[] sendBuffer = new byte[BUFFER_SIZE];

  //Other stuff that helps handle the buffers and ensure complete messages,
  //  even when TCP breaks up packets.
}

person chezy525    schedule 12.04.2011    source источник


Ответы (2)


Может быть, для того, чтобы получить фактическое исключение, попробуйте выяснить, какая библиотека ему нужна, и развернуть ее?

person oleksii    schedule 25.04.2011

Если сообщение не отображается на вашем устройстве, потому что сообщение не установлено на вашем устройстве. Вы должны установить netcf.messages.cab. Вы найдете это здесь:

C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE\Diagnostics

После установки этого CAB-файла снова запустите приложение и опубликуйте полученную новую ошибку.

person etalon11    schedule 03.02.2016