Roland M Smith Ответов: 0

Вопрос о winsock и IPv6


Я написал dll на C++ , которая позволяет мне выполнять функции Winsock из кода PowerBuilder.

Для IPv4 это отлично работает, но я получаю ошибку в IPv6. Я начинаю с функций UDP, потому что они проще. Следующая ошибка возникает на "Отправить":

Запрошенный адрес недействителен в его контексте

В приведенном ниже коде UD. family будет иметь значение AF_INET или AF_NET6.

Что я уже пробовал:

// method of_sendto (Unicode String)
PBXRESULT winsock::fn_sendto_u(PBCallInfo * ci)
{
   PBXRESULT pbxr = PBX_OK;
   SOCKET SendSocket = INVALID_SOCKET;
   sockaddr_in SendAddr4;
   sockaddr_in6 SendAddr6;
   USHORT port;
   int iResult = 0;
   LPCTSTR lpHostName = NULL;
   LPCTSTR lpMessage = NULL;
   int nBytes = 0, nLeft = 0, idx = 0;

   // get arguments
   pbstring arg0 = ci->pArgs->GetAt(0)->GetString();
   lpHostName = ud.session->GetString(arg0);
   port = ci->pArgs->GetAt(1)->GetUint();
   pbstring arg2 = ci->pArgs->GetAt(2)->GetString();
   lpMessage = ud.session->GetString(arg2);
   nBytes = (int) _tcslen(lpMessage) * sizeof(TCHAR);

   // create a socket
   SendSocket = socket(ud.family, SOCK_DGRAM, IPPROTO_UDP);
   if (SendSocket == INVALID_SOCKET) {
      // set the return value
      ci->returnValue->SetBool(FALSE);
   	return pbxr;
   }

   switch(ud.family) {
      case AF_INET:
         SendAddr4.sin_family = AF_INET;
         SendAddr4.sin_port = htons(port);
         InetPtonW(AF_INET, lpHostName, &SendAddr4.sin_addr);
         break;
      case AF_INET6:
         SendAddr6.sin6_family = AF_INET6;
         SendAddr6.sin6_port = htons(port);
         InetPtonW(AF_INET6, lpHostName, &SendAddr6.sin6_addr);
         break;
   }

   nLeft = nBytes;
   while (nLeft > 0) {
      // send the message
      switch(ud.family) {
         case AF_INET:
            iResult = sendto(SendSocket, (char*) lpMessage + idx, (int) nLeft, 0, 
                                 (SOCKADDR *) &SendAddr4, sizeof(SendAddr4));
            break;
         case AF_INET6:
            iResult = sendto(SendSocket, (char*) lpMessage + idx, (int) nLeft, 0, 
                                 (SOCKADDR *) &SendAddr6, sizeof(SendAddr6));
            break;
      }
      if (iResult == SOCKET_ERROR) {
         // save error and close socket
         iResult = WSAGetLastError();
         closesocket(SendSocket);
         WSASetLastError(iResult);

         // set the return value
         ci->returnValue->SetBool(FALSE);
         return pbxr;
      }
      nLeft -= iResult;
      idx += iResult;
   }

   // close the socket
   closesocket(SendSocket);

   // set the return value
   ci->returnValue->SetBool(TRUE);

   return pbxr;
}

Jochen Arndt

Передаете ли вы действительный IPv6-адрес?
Проверьте возвращаемое значение InetPton, чтобы убедиться в этом.

Roland M Smith

Я добавил код для проверки возврата из InetPton, и он работает. Я передаю действительный IP-адрес версии 6. Сообщение об ошибке поступает от "отправить".

0 Ответов