我有以下设置:
服务器将通过蓝牙连接到多个发送离散信号的设备。然后将有n个客户端可以查询服务器(可能通过Web服务)连接设备并收听他们想要的设备的信号。
我认为实现这一点的最佳方法是:当服务器通过BT连接到设备时,它将打开一个Socket到本地端口并在那里发送数据。当客户端询问可用设备时,服务器将返回一个字典,然后客户端只需要监听该端口。
但我在套接字实现方面遇到了一些问题。如何创建信号并将其写入本地端口?
这是我到目前为止所得到的:
class Device {
...
public EndPoint Connect() {
// create a bt connection to the device
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var endPoint = new IPEndPoint(IPAddress.Parse(_localIp), 0);
_socket.Bind(endPoint);
return endPoint;
}
private void OnBtDataReceived(object sender, wclDataEventArgs e) {
_socket.Send(e.Data);
}
}
但是当到达_socket.Send(e.Data)时;我收到以下例外:
不允许发送或接收数据的请求,因为套接字未连接(使用sendto调用在数据报套接字上发送时)没有提供地址
这是正确的方法,但需要有人连接到套接字才能读取数据吗?
答案 0 :(得分:1)
使用TCP时,您无需拨打Bind()
,但需要拨打Connect()
。
_socket.Connect(endPoint);
这假设您的代码_localIp
是您要连接的本地网络上的IP地址,而不是本地计算机上的网络适配器的IP地址您想要用于连接。
Bind()
做的是将套接字绑定到本地(即当前计算机上)端点。如果您不关心使用什么网络适配器(这意味着您让系统根据目标IP决定),并且您也不关心使用哪个本地端口,则无需调用{{1} }。
答案 1 :(得分:1)
您可以使用UDP广播作为注释建议您不必建立连接的位置。服务器只是在一个端口上发送数据,任何感兴趣的客户端都可以在该端口上接收该数据。
如果要区分设备,可能需要在单独的端口上广播每个设备数据。这可能是你有很多设备的很多(不必要的)网络流量。
另一种选择是使用TCP。 您的服务器要侦听来自客户端的传入连接:
_socket.Bind(new IPEndPoint(IPAddress.Any, 1234));
_socket.Listen(10);
_socket.BeginAccept(onAccept, _socket);
在onAccept中,您可以访问clientsocket并可以发送数据或将引用存储到某个地方以便稍后发送数据:
private static void onAccept(IAsyncResult ar)
{
Socket clientSocket = ((Socket) ar.AsyncState).EndAccept(ar);
// begin to accept the next client connection
_socket.BeginAccept(onAccept, _socket);
// this is the socket you can send data to the connected client:
clientSocket.Send(data);
}
TCP方法的优势在于,只有连接的客户端和服务器知道连接的客户端数量时,服务器才会发送数据。