.NET-проблема асинхронного завершения работы TCP-сокета - PullRequest
4 голосов
/ 12 апреля 2011

У меня есть клиент-серверное приложение 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.
}

Ответы [ 2 ]

0 голосов
/ 03 февраля 2016

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

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

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

0 голосов
/ 25 апреля 2011

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

...