(возможно, я объяснил проблему с раздражающим уровнем детализации, версия tl;dr находится внизу)
Я пытался использовать JNA для создания простого тестового приложения Winsock на Java. Первой функцией, которую я вызвал, была WSAStartup(), использующая следующий код:
public interface Ws2_32 extends Library {
Ws2_32 INSTANCE = (Ws2_32) Native.loadLibrary("ws2_32", Ws2_32.class);
int WSAStartup(short version, LPWSADATA lpwsaData);
}
public static void main(String[] args){
LPWSADATA lpwsaData = new LPWSADATA();
short version = 2;
int result = Ws2_32.INSTANCE.WSAStartup(version,lpwsaData);
System.out.println("WSAStartup() returned: " + result);
if((resultado = Ws2_32.INSTANCE.WSAStartup(version,lpwsaData)) == 0){
System.out.println("LPWSADATA struct:");
System.out.println("wVersion: " + lpwsaData.wVersion);
System.out.println("wHighVersion: " + lpwsaData.wHighVersion);
System.out.print("szDescription: ");
for(byte b : lpwsaData.szDescription){
System.out.print((char) b);
}
System.out.print("\n");
System.out.print("szSystemStatus: ");
for(byte b : lpwsaData.szSystemStatus){
System.out.print((char) b);
}
System.out.print("\n");
System.out.println("iMaxSockets: " + lpwsaData.iMaxSockets);
System.out.println("iMaxUdpDg: " + lpwsaData.iMaxUdpDg");
}
}
Это работает, и я получаю следующие значения:
wВерсия: 2
wHighVersion: 514
szОписание: WinSock 2.0
szSystemStatus: работает
iMaxSockets: 0
iMaxUdpDg: 0
После успешного возврата WSAStartup() я попытался вызвать WSAEnumProtocols(), но получил следующую ошибку:
Исключение в потоке «основной» java.lang.UnsatisfiedLinkError: ошибка при поиске функции «WSAEnumProtocols»: указанная процедура не найдена.
Затем я открыл ws2_32.dll с помощью Dependency Walker и обнаружил, что функции с таким именем нет. Я нашел только 3 с похожим именем: WSAEnumProtocolsA(), WSAEnumProtocolsW() и WSCEnumProtocols(). Я собираюсь использовать WSAEnumProtocolsA() в качестве примера, но я использовал следующую процедуру со всеми тремя и получил одинаковые результаты:
Сначала я вызвал WSAStartup(), и никакой ошибки не было возвращено. Согласно определению WSAEnumProtocols в MSDN, первый вызов функции должен быть примерно таким: WSAEnumProtocols(null, wsaprotocol_info, lpdwBufferLength) буфер. Если эта длина равна нулю, то функция должна вернуть -1 (SOCKET_ERROR), а вызов WSAGetLastError() должен вернуть WSAENOBUFS, что означает, что буфер недостаточно велик, чтобы содержать информацию, возвращаемую WSAEnumProtocols(), и должен установить переменную lpdwBufferLength. с минимальным размером буфера, который можно передать в WSAEnumProtocols для получения всей запрошенной информации. Я не могу заставить это работать. WSAEnumProtocols() возвращает -1, но значение lpdwBufferLength не изменяется, а WSAGetLastError() возвращает 0 вместо 10055 (WSAENOBUFS)
Я также пытался использовать WSASetLastError() и установить для него другой код ошибки, а затем вызвать WSAGetLastError(), но он всегда возвращал 0.
tl;dr Я не могу заставить WSAEnumProtocols(null, wsaprotocol_info, lpdwBufferLength) работать. WSAEnumProtocols() возвращает -1, но значение lpdwBufferLength не изменяется, а WSAGetLastError() возвращает 0 вместо 10055 (WSAENOBUFS)
ОБНОВЛЕНИЕ:
Это интерфейс, который я использую для объявления функций Winsock.
public interface Ws2_32 extends Library {
Ws2_32 INSTANCE = (Ws2_32) Native.loadLibrary("ws2_32", Ws2_32.class);
int WSAStartup(short version, LPWSADATA lpwsaData);
int WSAEnumProtocolsW(int[] lpiProtocols, WSAPROTOCOL_INFO lpProtocolBuffer, int lpdwBufferLength);
int WSACleanup();
int WSAGetLastError();
int WSASetLastError(int iError);
}
Это код, из которого я вызываю функции:
public class TestWSAEnumProtocolsA {
public void start(){
WSAPROTOCOL_INFO wsaprotocol_info = new WSAPROTOCOL_INFO();
LPWSADATA lpwsaData = new LPWSADATA();
int lpdwBufferLength = -2;
int result = 0;
short version = 514;
if((result = Ws2_32.INSTANCE.WSAStartup(version, lpwsaData)) != 0){
System.out.println("Error #" + result + " at WSAStartup()");
return;
} else {
System.out.println("WSAStartup() finished correctly.");
if((result = Ws2_32.INSTANCE.WSAEnumProtocols(null, wsaprotocol_info, lpdwBufferLength)) == -1){
System.out.println("WSAEnumProtocolsW() returned: " + result);
System.out.println("lpdwBufferLength is: " + lpdwBufferLength);
System.out.println("WSAGetLastError() returned: " + Ws2_32.INSTANCE.WSAGetLastError());
System.out.println("Now I'm setting it to 10004");
Ws2_32.INSTANCE.WSASetLastError(10004);
System.out.println("WSAGetLastError() returned: " + Ws2_32.INSTANCE.WSAGetLastError());
}
}
}
}
Этот код выдал следующий результат:
WSAStartup() завершен правильно.
WSAEnumProtocolsW() вернул: -1
lpdwBufferLength: -2
WSAGetLastError() возвращено: 0
Теперь я устанавливаю его на 10004
WSAGetLastError() возвращено: 0
Вот как я определил структуры, которые я использую при вызове этих функций:
public class WinSock2_structs {
public static class LPWSADATA extends Structure{
public short wVersion;
public short wHighVersion;
public byte szDescription[] = new byte[256+1];
public byte szSystemStatus[] = new byte[128+1];
public short iMaxSockets;
public short iMaxUdpDg;
public char lpVendorInfo;
}
public static class WSAPROTOCOLCHAIN extends Structure{
public int ChainLen;
public int ChainEntries[] = new int[7];
}
public static class GUID extends Structure{
public int Data1;
public short Data2;
public short Data3;
public short Data4;
public byte Data5[] = new byte[8];
}
public static class WSAPROTOCOL_INFO extends Structure{
public int dwServiceFlags1;
public int dwServiceFlags2;
public int dwServiceFlags3;
public int dwServiceFlags4;
public int dwProviderFlags;
public GUID ProviderId;
public int dwCatalogEntryId;
public WSAPROTOCOLCHAIN ProtocolChain;
public int iVersion;
public int iAddressFamily;
public int iMaxSockAddr;
public int iMinSockAddr;
public int iSocketType;
public int iProtocol;
public int iProtocolMaxOffset;
public int iNetworkByteOrder;
public int iSecurityScheme;
public int dwMessageSize;
public int dwProviderReserved;
public char szProtocol[] = new char[256];
}
}
WSAEnumProtocols()
иWSAGetLastError()
. - person Remy Lebeau   schedule 01.03.2013