📄 bluetoothlistener.cs
字号:
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using bluetoothX;
namespace bluetoothX
{
public class BluetoothListener
{
private bool active = false;
private BluetoothEndPoint serverEP;
private int serviceHandle;
private ServiceRecord serviceRecord;
private int channelOffset;
private ServiceClass codService;
#region Constructor
public BluetoothListener(Guid service)
{
this.serverEP = new BluetoothEndPoint(BluetoothAddress.None, service);
serverSocket = new Socket(AddressFamily32.Bluetooth, SocketType.Stream, BluetoothProtocolType.RFComm);
}
public BluetoothListener(BluetoothAddress localaddr, Guid service)
{
if (localaddr == null) {
throw new ArgumentNullException("localaddr");
}
if (service == Guid.Empty) {
throw new ArgumentNullException("service");
}
this.serverEP = new BluetoothEndPoint(localaddr, service);
serverSocket = new Socket(AddressFamily32.Bluetooth, SocketType.Stream, BluetoothProtocolType.RFComm);
}
public BluetoothListener(BluetoothEndPoint localEP)
{
if (localEP == null)
{
throw new ArgumentNullException("localEP");
}
this.serverEP = localEP;
serverSocket = new Socket(AddressFamily32.Bluetooth, SocketType.Stream, BluetoothProtocolType.RFComm);
}
public BluetoothListener(Guid service, byte[] sdpRecord, int channelOffset)
: this(service)
{
serviceRecord = new ServiceRecord(sdpRecord);
this.channelOffset = channelOffset;
}
public BluetoothListener(BluetoothAddress localaddr, Guid service, byte[] sdpRecord, int channelOffset)
: this(localaddr, service)
{
serviceRecord = new ServiceRecord(sdpRecord);
this.channelOffset = channelOffset;
}
public BluetoothListener(BluetoothEndPoint localEP, byte[] sdpRecord, int channelOffset)
: this(localEP)
{
serviceRecord = new ServiceRecord(sdpRecord);
this.channelOffset = channelOffset;
}
#endregion
#region Local EndPoint
public BluetoothEndPoint LocalEndPoint
{
get
{
if (!active)
{
return serverEP;
}
return (BluetoothEndPoint)serverSocket.LocalEndPoint;
}
}
#endregion
#region Service Class
public ServiceClass ServiceClass
{
get
{
return codService;
}
set
{
codService = value;
}
}
#endregion
#region Server
private Socket serverSocket;
public Socket Server
{
get
{
return serverSocket;
}
}
#endregion
#region Start
public void Start()
{
this.Start(int.MaxValue);
}
public void Start(int backlog)
{
if ((backlog > int.MaxValue) || (backlog < 0))
{
throw new ArgumentOutOfRangeException("backlog");
}
if (serverSocket == null)
{
throw new InvalidOperationException("The socket handle is not valid.");
}
if (!active)
{
serverSocket.Bind(serverEP);
//if we have a raw SDP record use that, otherwise we build a basic one
if (serviceRecord == null)
{
SdpRecordTemp srt = new SdpRecordTemp();
srt.Service = HostToNetworkOrder(this.serverEP.Service);
srt.Channel = (byte)((BluetoothEndPoint)serverSocket.LocalEndPoint).Port;
serviceRecord = new ServiceRecord(srt.ToByteArray());
}
else
{
serviceRecord.ToByteArray()[channelOffset] = (byte)((BluetoothEndPoint)serverSocket.LocalEndPoint).Port;
}
serviceHandle = SetService(serviceRecord.ToByteArray(), codService);
serverSocket.Listen(backlog);
active = true;
}
}
#endregion
#region Stop
/// <summary>
/// Stops the socket from monitoring connections.
/// </summary>
public void Stop()
{
if(serverSocket!=null)
{
//remove service registration
if(serviceHandle != 0)
{
RemoveService(serviceHandle, this.ServiceRecord.ToByteArray());
serviceHandle = 0;
}
serverSocket.Close();
serverSocket = null;
}
active = false;
serverSocket = new Socket(AddressFamily32.Bluetooth, SocketType.Stream, BluetoothProtocolType.RFComm);
}
#endregion
#region Accept
#region Async Socket
public IAsyncResult BeginAcceptSocket(AsyncCallback callback, object state)
{
if (!active)
{
throw new InvalidOperationException("Not listening. You must call the Start() method before calling this method.");
}
return serverSocket.BeginAccept(callback, state);
}
public Socket EndAcceptSocket(IAsyncResult asyncResult)
{
if (asyncResult == null)
{
throw new ArgumentNullException("asyncResult");
}
return serverSocket.EndAccept(asyncResult);
}
#endregion
#region Async Client
public IAsyncResult BeginAcceptBluetoothClient(AsyncCallback callback, object state)
{
if (!active)
{
throw new InvalidOperationException("Not listening. You must call the Start() method before calling this method.");
}
return serverSocket.BeginAccept(callback, state);
}
public BluetoothClient EndAcceptBluetoothClient(IAsyncResult asyncResult)
{
if (asyncResult == null)
{
throw new ArgumentNullException("asyncResult");
}
Socket s = serverSocket.EndAccept(asyncResult);
return new BluetoothClient(s);
}
#endregion
public Socket AcceptSocket()
{
if (!active)
{
throw new InvalidOperationException("Not listening. You must call the Start() method before calling this method.");
}
return serverSocket.Accept();
}
public BluetoothClient AcceptBluetoothClient()
{
Socket s = AcceptSocket();
return new BluetoothClient(s);
}
#endregion
#region Pending
public bool Pending()
{
if (!active)
{
throw new InvalidOperationException("Not listening. You must call the Start() method before calling this method.");
}
return serverSocket.Poll(0, SelectMode.SelectRead);
}
#endregion
#region Service Record
public ServiceRecord ServiceRecord
{
get
{
return this.serviceRecord;
}
}
#endregion
#region Service
private static void RemoveService(int handle, byte[] sdpRecord)
{
BTHNS_SETBLOB blob = new BTHNS_SETBLOB(sdpRecord);
blob.Handle = handle;
WSAQUERYSET qs = new WSAQUERYSET();
qs.dwSize = 60;
qs.dwNameSpace = 16;
GCHandle hBlob = GCHandle.Alloc(blob.ToByteArray(), GCHandleType.Pinned);
BLOB b = new BLOB(blob.Length, hBlob.AddrOfPinnedObject());
GCHandle hb = GCHandle.Alloc(b, GCHandleType.Pinned);
qs.lpBlob = hb.AddrOfPinnedObject();
try
{
int hresult = NativeMethods.WSASetService(ref qs, WSAESETSERVICEOP.RNRSERVICE_DELETE, 0);
BluetoothClient.ThrowSocketExceptionForHR(hresult);
}
finally
{
hb.Free();
hBlob.Free();
}
}
private static int SetService(byte[] sdpRecord, ServiceClass cod)
{
BTHNS_SETBLOB blob = new BTHNS_SETBLOB(sdpRecord);
blob.CodService = (uint)cod;
WSAQUERYSET qs = new WSAQUERYSET();
qs.dwSize = 60;
qs.dwNameSpace = 16;
GCHandle hBlob = GCHandle.Alloc(blob.ToByteArray(), GCHandleType.Pinned);
BLOB b = new BLOB(blob.Length, hBlob.AddrOfPinnedObject());
GCHandle hb = GCHandle.Alloc(b, GCHandleType.Pinned);
qs.lpBlob = hb.AddrOfPinnedObject();
try
{
int hresult = NativeMethods.WSASetService(ref qs, WSAESETSERVICEOP.RNRSERVICE_REGISTER, 0);
BluetoothClient.ThrowSocketExceptionForHR(hresult);
}
finally
{
hb.Free();
hBlob.Free();
}
return blob.Handle;
}
#endregion
#region Host To Network Order
internal static Guid HostToNetworkOrder(Guid hostGuid)
{
byte[] guidBytes = hostGuid.ToByteArray();
BitConverter.GetBytes(IPAddress.HostToNetworkOrder(BitConverter.ToInt32(guidBytes, 0))).CopyTo(guidBytes, 0);
BitConverter.GetBytes(IPAddress.HostToNetworkOrder(BitConverter.ToInt16(guidBytes, 4))).CopyTo(guidBytes, 4);
BitConverter.GetBytes(IPAddress.HostToNetworkOrder(BitConverter.ToInt16(guidBytes, 6))).CopyTo(guidBytes, 6);
return new Guid(guidBytes);
}
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -