0

I have writen an IOCP program and I am testing it through VPN.

It was all working OK, but then the server disconnected and the client GetQueuedCompletionStatus didn't trigger an exception.

I waited for one day,cbut it didn't get better. When I changed to a new VPN, the problem was solved, and I didn't get that problem later.

What's wrong? Has anybody seen the same problem before?

Moshe Katz
  • 15,992
  • 7
  • 69
  • 116
  • What language? What does your source look like. What does "the problem solved" mean? It is unclear what you are asking, please describe specifically what problem you are having - visit the "How to Ask" page - http://stackoverflow.com/help/how-to-ask. Asking a clearer question will help us help you. – frasnian Jan 29 '15 at 05:09

2 Answers2

0
enter code here

    enter code here

#include "XYTransport.h"
//---------------------------------------------------------------------------
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
//---------------------------------------------------------------------------
#define XYTCP_LIST_CLIENT0             0
#define XYTCP_LIST_CLIENT1             1
//---------------------------------------------------------------------------
#define XYTRANSPORT_TYPE_TCP_OPEN           0
#define XYTRANSPORT_TYPE_TCP_RECV           1
#define XYTRANSPORT_TYPE_TCP_SEND           2
//---------------------------------------------------------------------------
typedef struct tagXYOVERLAPPED
{
 OVERLAPPED o;

 SOCKET s;

 UINT flags;

 WSABUF wb;
}XYOVERLAPPED, *PXYOVERLAPPED;
//---------------------------------------------------------------------------
inline LPVOID XYAlloc(HANDLE heap, UINT size)
{
 return(HeapAlloc(heap, 0, size));
}
inline VOID XYFree(HANDLE heap, LPVOID lpdata)
{
 HeapFree(heap, 0, lpdata);
}
inline PXYOVERLAPPED XYOverlappedPop(PXYTRANSPORT pt, LPBYTE buffer, SOCKET s)
{
 PXYOVERLAPPED pto = NULL;
 SOCKADDR_IN name;

 if (buffer == NULL)
 {
  buffer = (LPBYTE)VirtualAlloc(NULL, pt->bufferlength, MEM_COMMIT, PAGE_READWRITE);
 }
 if (buffer != NULL)
 {
  pto = (PXYOVERLAPPED)MALLOC(sizeof(XYOVERLAPPED));
  if (pto != NULL)
  {
   pto->wb.buf = (char *)buffer;
   pto->wb.len = pt->bufferlength;

   if (s == INVALID_SOCKET)
   {
    pto->s = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (pto->s != INVALID_SOCKET)
    {
     ZeroMemory(&name, sizeof(name));
     name.sin_family = AF_INET;
     name.sin_addr.S_un.S_addr = INADDR_ANY;
     //name.sin_port = fn_htons(0);
     name.sin_port = 0;
     if (bind(pto->s, (const SOCKADDR *)&name, sizeof(name)) == 0)
     {
      if (CreateIoCompletionPort((HANDLE)pto->s, pt->hcompletion, (ULONG_PTR)pto->s, 0) == pt->hcompletion)
      {
       //
      }
     }
    }
   }
   else
   {
    pto->s = s;
   }
  }
 }

 return(pto);
}

BOOL XYTCPPushReceive(PXYTRANSPORT pt, PXYOVERLAPPED pto, SOCKET s)
{
 DWORD numberofbytes;
 DWORD flags = 0;
 BOOL result;
 int error;

 if (pto == NULL)
 {
  pto = XYOverlappedPop(pt, NULL, s);
 }

 ZeroMemory(&pto->o, sizeof(OVERLAPPED));

 pto->flags = XYTRANSPORT_TYPE_TCP_RECV;

 result = WSARecv(pto->s, &pto->wb, 1, &numberofbytes, &flags, &pto->o, NULL) != SOCKET_ERROR;
 if (!result)
 {
  error = WSAGetLastError();
  result = error == WSA_IO_PENDING;
  if (!result)
  {
   printf("WSARecv\n");
  }
 }

 return(result);
}

inline BOOL XYTCPPushSend(PXYTRANSPORT pt, PXYOVERLAPPED pto)
{
 DWORD numberofbytes;
 ULONG flags = MSG_PARTIAL;
 BOOL result;
 int error;

 ZeroMemory(&pto->o, sizeof(OVERLAPPED));

 pto->flags = XYTRANSPORT_TYPE_TCP_SEND;

 //
 pto->wb.len = 1024;
 //

 result = WSASend(pto->s, &pto->wb, 1, &numberofbytes, flags, &pto->o, NULL) != SOCKET_ERROR;
 if (!result)
 {
  error = WSAGetLastError();
  result = error == WSA_IO_PENDING;
  if (!result)
  {
   printf("Send Error\n");
  }
 }

 return(result);
}

DWORD WINAPI XYTransportWorkProc(LPVOID parameter)
{
 PXYTRANSPORT pt = (PXYTRANSPORT)parameter;
 HANDLE hcompletion = pt->hcompletion;
 LPOVERLAPPED po;
 PXYOVERLAPPED pto;
  ULONG_PTR completionkey;
 DWORD numberofbytes;
 SOCKET s;
 BOOL flag;
 UINT type;
 UINT count;
 UINT error;

 while(pt->working)
  {
  flag = GetQueuedCompletionStatus(hcompletion, &numberofbytes, &completionkey, &po, INFINITE);

  if (po != NULL)
  {
   pto = (PXYOVERLAPPED)CONTAINING_RECORD(po, XYOVERLAPPED, o);

   s = (SOCKET)completionkey;

   type = pto->flags;

   if (!flag)
   {
    //OutputDebugValue(_T("Except Error"), type, numberofbytes);
    printf("Except Error %d\n", type);
   }
   if (numberofbytes == 0)
   {
    //OutputDebugValue(_T("Length Error"), type);
    printf("Length Error %d\n", type);
   }

   if (!flag)
   {
    numberofbytes = 0;
   }

   switch (type)
   {
   case XYTRANSPORT_TYPE_TCP_OPEN:
    if (flag)
    {
     setsockopt(s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);

     XYTCPPushSend(pt, pto);
     printf("connected\n");

     if (!XYTCPPushReceive(pt, NULL, s))
     {
      //
     }
     else
     {
      printf("post recv\n");
     }
     break;
    }
    break;
   case XYTRANSPORT_TYPE_TCP_RECV:
    if (numberofbytes > 0)
    {
     XYTCPPushReceive(pt, pto, s);

     //OutputDebugString(_T("Recv"));
     printf("Recv %d\n", numberofbytes);
    }
    else
    {
     printf("Recv Error\n");
    }
    break;
   case XYTRANSPORT_TYPE_TCP_SEND:
    if (numberofbytes > 0)
    {
     XYTCPPushSend(pt, pto);
     printf("Send %d\n", numberofbytes);
    }
    else
    {
     printf("Send Except\n");
    }
    break;
   default:
    break;
   }
  }
  else
  {
   printf("Quit %d, %d", GetCurrentThreadId(), flag);

   break;
  }
  }

 return(0);
}

VOID XYTransportStartup(PXYTRANSPORT pt, UINT pagesize)
{
 pt->hcompletion = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
 if (pt->hcompletion != INVALID_HANDLE_VALUE)
 {
  pt->lpfnConnectEx = NULL;

  pt->bufferlength = pagesize;

  pt->working = TRUE;

  pt->hthread = CreateThread(NULL, 0, XYTransportWorkProc, (LPVOID)pt, 0, NULL);
 }
}

BOOL XYTCPConnect(PXYTRANSPORT pt, const CHAR *host, USHORT port)
{
 GUID id = WSAID_CONNECTEX;
 DWORD numberofbytes = 0;
 PXYOVERLAPPED pto;
 SOCKADDR_IN name;
 BOOL result = FALSE;
 int error;

 pto = XYOverlappedPop(pt, NULL, INVALID_SOCKET);

 if (pt->lpfnConnectEx != NULL || WSAIoctl(pto->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &id, sizeof(id), &pt->lpfnConnectEx, sizeof(pt->lpfnConnectEx), &numberofbytes, NULL, NULL) != SOCKET_ERROR)
 {
  ZeroMemory(&pto->o, sizeof(OVERLAPPED));

  pto->flags = XYTRANSPORT_TYPE_TCP_OPEN;

  ZeroMemory(&name, sizeof(name));
  name.sin_family = AF_INET;
  name.sin_port = htons(port);
  name.sin_addr.S_un.S_addr = inet_addr(host);
  if (name.sin_addr.S_un.S_addr != INADDR_NONE)
  {
   numberofbytes = 0;

   result = pt->lpfnConnectEx(pto->s, (SOCKADDR *)&name, sizeof(name), NULL, 0, &numberofbytes, &pto->o);
   if(!result)
   {
    error = WSAGetLastError();
    result = error == ERROR_IO_PENDING;
    if (!result)
    {
     printf("ConnectEx error\n");
    }
   }
  }
 }

 return(result);
}
//---------------------------------------------------------------------------
0

the client Thrown an exception is what i desired,so i can know.

I am using C language to write. Under normal circumstances, disconnect one end and the other end will trigger an exception, but I have found that sometimes have to wait a very long time, at least I'm waiting for more than one day are not triggered, and sometimes even in the off time can continue to deliver WSASend success for some time.