Question

I have the following setup:

The server will connect via Bluetooth to several devices that are sending a discrete signal. Then there will be n clients that can inquiry the server (via web services probably) for which devices are connected and listen to the signal from the devices they want.

I think the best way to implement this is: when the server connects to a device via BT, it will open a Socket to a local port and send the data there. When a client ask for the available devices, the server will return a Dictionary and then the client just have to listen to that port.

But i'm having some problems with the socket implementation. How can I create and write the signal to a local port?

This is what I got so far:

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);
    }
}

But when reaching the _socket.Send(e.Data); I receive the following exception:

A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied

Is this the right approach but it needs to have someone connected to the socket to read the data?

Was it helpful?

Solution

You can use UDP Broadcast as the comments suggest where you don't have to establish a connection. The server justs sends the data out on one port and any interested client can receive that data on that port.

If you want to distinguish between your devices you might have to broadcast every devices data on a separate port. That might be a lot of (unnecessary) network traffic whn you have many devices.

The other option is using TCP. Your server as to listen for incoming connections from your clients:

_socket.Bind(new IPEndPoint(IPAddress.Any, 1234));
_socket.Listen(10);
_socket.BeginAccept(onAccept, _socket);

In onAccept you have access to the clientsocket and can send data or store the reference to the socket somewhere to send data later on:

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);
}

The TCP approach has the advantage that your server only sends data when there are connected clients and your server is aware of the number of clients connected.

OTHER TIPS

When using TCP, you don't need to call Bind(), but you need to call Connect().

_socket.Connect(endPoint);

This assumes that in your code _localIp is an IP address on the local network you want to connect to and not an IP address of a network adapter on the local computer that you want to use for the connection.

What Bind() does is to bind the socket to a local (i.e. on the current computer) end point. If you don't care what network adapter is used (which means you let the system decide that based on the target IP), and you also don't care what local port is used, there is no need to call Bind().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top