📄 bluetoothclient.cs
字号:
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using bluetoothX;
using Microsoft.Win32;
namespace bluetoothX
{
public class BluetoothClient : IDisposable
{
private bool cleanedUp = false;
private bool authenticate = false;
private bool encrypt = false;
#region Constructor
public BluetoothClient()
{
try
{
this.Client = new Socket(AddressFamily32.Bluetooth, SocketType.Stream, BluetoothProtocolType.RFComm);
}
catch (SocketException se)
{
throw new PlatformNotSupportedException("Does not support the Bluetooth stack on this device.", se);
}
}
public BluetoothClient(BluetoothEndPoint localEP) : this()
{
if (localEP == null)
{
throw new ArgumentNullException("localEP");
}
this.Client.Bind(localEP);
}
internal BluetoothClient(Socket acceptedSocket)
{
this.Client = acceptedSocket;
active = true;
}
#endregion
#region Query Length
private TimeSpan inquiryLength = new TimeSpan(0,0,10);
public TimeSpan InquiryLength
{
get
{
return inquiryLength;
}
set
{
if((value.TotalSeconds > 0) && (value.TotalSeconds <= 60))
{
inquiryLength = value;
}
else
{
throw new ArgumentOutOfRangeException("QueryLength must be a positive timespan between 0 and 60 seconds.");
}
}
}
#endregion
#region Discover Devices
public BluetoothDeviceInfo[] DiscoverDevices()
{
return DiscoverDevices(255,true,true,true);
}
public BluetoothDeviceInfo[] DiscoverDevices(int maxDevices)
{
return DiscoverDevices(maxDevices,true,true,true);
}
public BluetoothDeviceInfo[] DiscoverDevices(int maxDevices, bool authenticated, bool remembered, bool unknown)
{
int discoveredDevices = 0;
ArrayList al = new ArrayList();
int handle = 0;
int lookupresult = 0;
byte[] buffer = new byte[1024];
BitConverter.GetBytes((int)60).CopyTo(buffer, 0);
BitConverter.GetBytes((int)16).CopyTo(buffer, 20);
int bufferlen = buffer.Length;
BTHNS_INQUIRYBLOB bib = new BTHNS_INQUIRYBLOB();
bib.LAP = 0x9E8B33;
bib.length = Convert.ToByte(inquiryLength.TotalSeconds);
GCHandle hBib = GCHandle.Alloc(bib, GCHandleType.Pinned);
IntPtr pBib = hBib.AddrOfPinnedObject();
BLOB b = new BLOB(8, pBib);
GCHandle hBlob = GCHandle.Alloc(b, GCHandleType.Pinned);
BitConverter.GetBytes(hBlob.AddrOfPinnedObject().ToInt32()).CopyTo(buffer, 56);
lookupresult = NativeMethods.WSALookupServiceBegin(buffer, LookupFlags.Containers | LookupFlags.FlushCache, ref handle);
hBlob.Free();
while(discoveredDevices < maxDevices && lookupresult != -1)
{
lookupresult = NativeMethods.WSALookupServiceNext(handle, LookupFlags.ReturnAddr , ref bufferlen, buffer);
if(lookupresult != -1)
{
//increment found count
discoveredDevices++;
//status
BTHNS_RESULT status = (BTHNS_RESULT)BitConverter.ToInt32(buffer, 52);
if((authenticated && ((status & BTHNS_RESULT.Authenticated)==BTHNS_RESULT.Authenticated)) | (remembered && ((status & BTHNS_RESULT.Remembered)==BTHNS_RESULT.Remembered)) | (unknown && ((status & BTHNS_RESULT.Unknown)==BTHNS_RESULT.Unknown)))
{
IntPtr bufferptr = (IntPtr)BitConverter.ToInt32(buffer, 48);
//remote socket address
IntPtr sockaddrptr = (IntPtr)Marshal.ReadInt32((IntPtr)bufferptr, 8);
//remote socket len
int sockaddrlen = Marshal.ReadInt32(bufferptr, 12);
SocketAddress btsa = new SocketAddress(AddressFamily32.Bluetooth, sockaddrlen);
for(int sockbyte = 0; sockbyte < sockaddrlen; sockbyte++)
{
btsa[sockbyte] = Marshal.ReadByte(sockaddrptr, sockbyte);
}
BluetoothEndPoint bep = new BluetoothEndPoint(null, BluetoothService.Empty);
bep = (BluetoothEndPoint)bep.Create(btsa);
//new deviceinfo
BluetoothDeviceInfo newdevice;
newdevice = new BluetoothDeviceInfo(bep.Address);
//add to discovered list
al.Add(newdevice);
}
}
}
//stop looking
if(handle!=0)
{
lookupresult = NativeMethods.WSALookupServiceEnd(handle);
}
//return results
if(al.Count == 0)
{
//special case for empty collection
return new BluetoothDeviceInfo[0]{};
}
return (BluetoothDeviceInfo[])al.ToArray(typeof(BluetoothDeviceInfo));
}
#endregion
#region Active
private bool active = false;
protected bool Active
{
get
{
return active;
}
set
{
active = value;
}
}
#endregion
#region Available
public int Available
{
get
{
return clientSocket.Available;
}
}
#endregion
#region Client
private Socket clientSocket;
public Socket Client
{
get
{
return clientSocket;
}
set
{
this.clientSocket = value;
}
}
#endregion
#region Connect
public void Connect(BluetoothEndPoint remoteEP)
{
if (cleanedUp)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
if (remoteEP == null)
{
throw new ArgumentNullException("remoteEP");
}
clientSocket.Connect(remoteEP);
active = true;
}
public void Connect(BluetoothAddress address, Guid service)
{
if (address == null)
{
throw new ArgumentNullException("address");
}
if (service==Guid.Empty)
{
throw new ArgumentNullException("service");
}
BluetoothEndPoint point = new BluetoothEndPoint(address, service);
this.Connect(point);
}
#region Begin Connect
public IAsyncResult BeginConnect(BluetoothAddress address, Guid service, AsyncCallback requestCallback, object state)
{
return this.Client.BeginConnect(new BluetoothEndPoint(address,service), requestCallback, state);
}
#endregion
#region End Connect
public void EndConnect(IAsyncResult asyncResult)
{
this.Client.EndConnect(asyncResult);
this.active = true;
}
#endregion
#endregion
#region Connected
public bool Connected
{
get
{
return clientSocket.Connected;
}
}
#endregion
#region Close
public void Close()
{
Dispose();
}
#endregion
#region Get Stream
private NetworkStream dataStream;
public NetworkStream GetStream()
{
if (cleanedUp)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
if (!this.Client.Connected)
{
throw new InvalidOperationException("The operation is not allowed on non-connected sockets.");
}
if (dataStream == null)
{
dataStream = new NetworkStream(this.Client, true);
}
return dataStream;
}
#endregion
#region Authenticate
public bool Authenticate
{
get
{
return authenticate;
}
set
{
clientSocket.SetSocketOption(BluetoothSocketOptionLevel.RFComm, BluetoothSocketOptionName.XPAuthenticate, (uint)(value ? 0xFFFFFFFF : 0));
authenticate = value;
}
}
#endregion
#region Encrypt
public bool Encrypt
{
get
{
return encrypt;
}
set
{
clientSocket.SetSocketOption(BluetoothSocketOptionLevel.RFComm, BluetoothSocketOptionName.Encrypt, (int)(value ? 1 : 0));
encrypt = value;
}
}
#endregion
#region Link Key
public Guid LinkKey
{
get
{
byte[] link = clientSocket.GetSocketOption(BluetoothSocketOptionLevel.RFComm, BluetoothSocketOptionName.GetLink, 32);
byte[] bytes = new byte[16];
Buffer.BlockCopy(link, 16, bytes, 0, 16);
return new Guid(bytes);
}
}
#endregion
#region Link Policy
public LinkPolicy LinkPolicy
{
get
{
byte[] policy = clientSocket.GetSocketOption(BluetoothSocketOptionLevel.RFComm, BluetoothSocketOptionName.GetLinkPolicy, 4);
return (LinkPolicy)BitConverter.ToInt32(policy, 0);
}
}
#endregion
#region Local Version
public BluetoothVersion LocalVersion
{
get
{
byte[] version = clientSocket.GetSocketOption(BluetoothSocketOptionLevel.RFComm, BluetoothSocketOptionName.GetLocalVersion, 16);
return new BluetoothVersion(version);
}
}
#endregion
#region Pin
public string Pin
{
set
{
if (clientSocket.Connected)
{
SetPin(((BluetoothEndPoint)clientSocket.RemoteEndPoint).Address, value);
}
else
{
SetPin(null, value);
}
}
}
public void SetPin(BluetoothAddress device, string pin)
{
byte[] link = new byte[32];
//copy remote device address
if(device != null)
{
Buffer.BlockCopy(device.ToByteArray(), 0, link, 8, 6);
}
//copy PIN
if(pin!=null & pin.Length > 0)
{
if(pin.Length > 16)
{
throw new ArgumentOutOfRangeException("PIN must be between 1 and 16 characters");
}
//copy pin bytes
byte[] pinbytes = System.Text.Encoding.ASCII.GetBytes(pin);
Buffer.BlockCopy(pinbytes, 0, link, 16, pin.Length);
BitConverter.GetBytes(pin.Length).CopyTo(link, 0);
}
clientSocket.SetSocketOption(BluetoothSocketOptionLevel.RFComm, BluetoothSocketOptionName.SetPin, link);
}
#endregion
#region Remote Machine Name
public string RemoteMachineName
{
get
{
return GetRemoteMachineName(clientSocket);
}
}
public string GetRemoteMachineName(BluetoothAddress a)
{
BluetoothDeviceInfo bdi = new BluetoothDeviceInfo(a);
return bdi.DeviceName;
}
public static string GetRemoteMachineName(Socket s)
{
BluetoothDeviceInfo bdi = new BluetoothDeviceInfo(((BluetoothEndPoint)s.RemoteEndPoint).Address);
return bdi.DeviceName;
}
#endregion
#region IDisposable Members
protected virtual void Dispose(bool disposing)
{
if(!cleanedUp)
{
if (disposing)
{
IDisposable idStream = dataStream;
if (idStream != null)
{
idStream.Dispose();
}
else
{
if (this.Client != null)
{
this.Client.Close();
this.Client = null;
}
}
GC.SuppressFinalize(this);
}
cleanedUp = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~BluetoothClient()
{
Dispose(false);
}
#endregion
#region Throw SocketException For HR
internal static void ThrowSocketExceptionForHR(int errorCode)
{
if (errorCode < 0)
{
int socketerror = 0;
socketerror = NativeMethods.WSAGetLastError();
throw new SocketException(socketerror);
}
}
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -