【发布时间】:2015-07-04 08:42:49
【问题描述】:
我正在尝试使用 Winsock2 API 接口扫描附近的蓝牙设备的 MAC 地址。
使用下面的代码我可以找到设备。但是,当我尝试使用 WSAAddressToString 获取他们的地址时,会出现 10022 (WSAEINVAL) 错误,提示“提供了无效参数”。
代码是:
uses
winsock2, bt_helper;
procedure test;
var
ulFlags: u_long;
QuerySet: WSAQUERYSET;
QuerySize: u_long;
HLookup: THandle;
Result: Integer;
pCSAddr: pCSADDR_INFO;
pDeviceInfo: PBTH_DEVICE_INFO;
pResults: lpWSAQUERYSET;
Buffer: array [0..999] of Byte;
ProtocolInfo: WSAPROTOCOL_INFO;
ProtocolInfoSize: Integer;
BufferLength, AddressSize: LongWord;
addressAsString: array [0..1999] of Char;
begin
WSAStartup ($0202, Data);
ulFlags:=
LUP_CONTAINERS or //device inquiry
LUP_RETURN_NAME or //Friendly device name (if available) will be returned in lpszServiceInstanceName
LUP_RETURN_ADDR or //BTH_ADDR will be returned in lpcsaBuffer member of WSAQUERYSET
LUP_FLUSHCACHE ; //Flush the device cache for all inquiries, except for the first inquiry
QuerySize:= SizeOf(WSAQuerySet);
ZeroMemory (@QuerySet, SizeOf(QuerySet));
QuerySet.dwNameSpace:= NS_BTH;
QuerySet.dwSize:= QuerySize;
Result:= WSALookupServiceBegin(@QuerySet, ulFlags, HLookup);
if Result = 0 then
begin
while true do
begin
bufferLength:= sizeof(buffer);
pResults:= lpWSAQUERYSET(@buffer);
Result:= WSALookupServiceNext (HLOOKUP, ulFlags, bufferLength, pResults);
if Result = 0 then
begin
// Get the device info, name, address, etc.
Memo1.Lines.Add(Format('The service instance name is %s', [pResults.lpszServiceInstanceName]));
//pCSAddr.LocalAddr.lpSockaddr.sa_family:= AF_INET;
pCSAddr:= PCSADDR_INFO(pResults.lpcsaBuffer);
pDeviceInfo:= PBTH_DEVICE_INFO(pResults.lpBlob);
// Print the local Bluetooth device address ...
AddressSize:= sizeof(addressAsString);
if WSAAddressToString(pCSAddr.LocalAddr.lpSockaddr^, pCSAddr.LocalAddr.iSockaddrLength,
@ProtocolInfo, @AddressAsString, AddressSize) = 0
then
Memo1.Lines.Add(Format ('The localAddress: %s', [AddressAsString]))
else
Memo1.Lines.Add(Format ('WSAAddressToString for localAddress failed with error code %d: %s',
[WSAGetLastError, SysErrorMessage (WSAGetLastError)]));
// Print the remote Bluetooth device address ...
AddressSize:= sizeof(addressAsString);
IF WSAAddressToString(pCSAddr.RemoteAddr.lpSockaddr^, pCSAddr.RemoteAddr.iSockaddrLength,
@ProtocolInfo, @AddressAsString, Addresssize) = 0
then
Memo1.Lines.Add (Format ('The remote device address: %s', [AddressAsString]))
else
Memo1.Lines.Add (Format ('WSAAddressToString for remoteAddress failed with error code %d: %s',
[WSAGetLastError, SysErrorMessage(WSAGetLastError)]));
end
else
begin
Memo1.Lines.Add(SysErrorMessage(WSAGetLastError));
break;
end;
end;
end;
WSALookupServiceEnd(HLookup);
这是备忘录中的结果:
The service instance name is BTDevice1
WSAAddressToString for localAddress failed with error code 10022: An invalid argument was supplied
WSAAddressToString for remoteAddress failed with error code 10022: An invalid argument was supplied
---------------------------------
No more results can be returned by WSALookupServiceNext
使用以下单元进行编译:
unit bt_helper;
interface
uses
winsock2, Winapi.Windows;
const
BTH_MAX_NAME_SIZE = 248;
BTHPROTO_RFCOMM= 3;
BT_PORT_ANY = -1;
type
BTH_ADDR = int64;
SOCKADDR_BTH = packed record
addressFamily :word; // Always AF_BTH
btAddr :BTH_ADDR; // Bluetooth device address
serviceClassId :TGUID; // [OPTIONAL] system will query SDP for port
port :dword; // RFCOMM channel or L2CAP PSM
end;
BTH_COD = ULONG;
_BTH_DEVICE_INFO = record
flags: ULONG; // Combination BDIF_Xxx flags
address: BTH_ADDR; // Address of remote device.
classOfDevice: BTH_COD; // Class Of Device.
name: array [0..BTH_MAX_NAME_SIZE - 1] of CHAR; // name of the device
end;
{$EXTERNALSYM _BTH_DEVICE_INFO}
BTH_DEVICE_INFO = _BTH_DEVICE_INFO;
{$EXTERNALSYM BTH_DEVICE_INFO}
PBTH_DEVICE_INFO = ^BTH_DEVICE_INFO;
{$EXTERNALSYM PBTH_DEVICE_INFO}
TBthDeviceInfo = BTH_DEVICE_INFO;
PBthDeviceInfo = PBTH_DEVICE_INFO;
implementation
end.
【问题讨论】:
-
使用 length() 代替 sizeof()
-
请附上一个可编译的例子?
-
WSAEINVAL的文档说 传递了一个无效参数。如果 lpsaAddress、dwAddressLength 或 lpdwAddressStringLength 参数为 NULL,则返回此错误。如果指定的地址不是有效的套接字地址,或者没有传输提供程序支持指定的地址族,也会返回此错误。您是否检查了这些条件? -
我不明白第二个问题(有效的套接字地址,传输提供商支持),但
lpsaAddress为零,lpsaAddressString 有它的默认值(随机数据)。 -
我无法理解该评论。在我看来,文档告诉你问题的答案是什么。
标签: delphi bluetooth delphi-xe2 winsock2