I'm writing a C# console application using the 32feet.Net library that creates two threads to search for and connect to different Bluetooth devices and then open up TCP sockets so that data can be passed to the devices via a network connection. I know this situation sounds completely bizarre, but I've been asked to do this by a senior colleague.
My code seems to work OK with only one device connected, although the Bluetooth connection does sometimes drop out after a couple of messages have been passed backwards and forwards. However, sometimes as soon as the second device connects I get an error saying System.net.sockets.socketexception a connection attempt failed because the connected party did not properly respond, other times the code just exits without throwing any exceptions.
I was wondering what is causing this, I've seen that the 32feet.Net library can support multiple connections. I'm wondering if I've made some errors, as I'm new to C#, .Net, and even Windows, and have never written any Bluetooth based code before.
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace BluetoothManager
{
class Program
{
static void Main(string[] args)
{
BTManager rover_btm = new BTManager();
BTManager base_btm = new BTManager();
base_btm.Port = 0xba5e;
rover_btm.Port = 17825;
base_btm.Name = "Base";
rover_btm.Name = "Rover";
base_btm.match = (args.Length >= 1 && args[0] != "") ? args[0] : "dev1";
rover_btm.match = (args.Length >= 2 && args[1] != "") ? args[1] : "dev2";
Console.WriteLine("Base Station match: " + base_btm.match);
Console.WriteLine("Rover match: " + rover_btm.match);
Thread Base = new Thread(new ThreadStart(base_btm.HandleThread));
Thread Rover = new Thread(new ThreadStart(rover_btm.HandleThread));
Base.Start();
Rover.Start();
Base.Join();
Rover.Join();
Console.Read();
}
}
}
BTManager.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Ports;
using InTheHand.Net.Sockets;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using Microsoft.Win32;
using System.IO;
namespace BluetoothManager
{
class BTManager
{
private static BluetoothDeviceInfo[] peers;
private BluetoothClient client;
private bool _isConnected = false;
private string _match;
private const string defpin = "0000";
private TcpListener tcpListener;
private int _port;
private string _name = "Not Named";
public string Name
{
get { return _name; }
set { _name = value; }
}
public int Port
{
get { return _port; }
set { _port = value; }
}
public bool IsConnected
{
get { return _isConnected; }
private set { _isConnected = value; }
}
public string match
{
get { return _match; }
set { _match = value; }
}
public BTManager()
{
client = new BluetoothClient();
}
public void HandleThread()
{
BluetoothDeviceInfo device;
while (!this.findDevice(out device)) ;
Console.WriteLine("About to pair");
int count = 0;
int max = 5;
while ((!(BluetoothSecurity.PairRequest(device.DeviceAddress, defpin))) && count < max)
{
Console.WriteLine("Pairing Failed, retrying");
count++;
Thread.Sleep(100);
}
if (count == max)
{
HandleThread();
}
else
{
Console.WriteLine("Paired..Beginning connect");
client.BeginConnect(device.DeviceAddress, BluetoothService.SerialPort, this.callback, client);
}
}
private void callback(IAsyncResult result)
{
client.EndConnect(result);
this.tcpListener = new TcpListener(IPAddress.Loopback, _port);
this.tcpListener.Start();
TcpClient TcpClient = this.tcpListener.AcceptTcpClient();
NetworkStream networkStream = TcpClient.GetStream();
Stream bluetoothStream = client.GetStream();
byte[] fromNetwork = new byte[1024];
byte[] fromBluetooth = new byte[1024];
while (client.Connected && TcpClient.Connected)
{
try
{
if (networkStream.CanRead)
{
Array.Clear(fromNetwork, 0, 1024);
networkStream.Read(fromNetwork, 0, 1024);
Console.WriteLine(Encoding.ASCII.GetString(fromNetwork));
bluetoothStream.Write(fromNetwork, 0, 1024);
bluetoothStream.Flush();
while (bluetoothStream.CanRead)
{
Array.Clear(fromBluetooth, 0, 1024);
bluetoothStream.Read(fromBluetooth, 0, 1024);
Console.WriteLine(Encoding.ASCII.GetString(fromNetwork));
networkStream.Write(fromBluetooth, 0, 1024);
networkStream.Flush();
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
this.HandleThread();
}
private bool findDevice(out BluetoothDeviceInfo device)
{
peers = client.DiscoverDevicesInRange();
device = Array.Find(peers, element => element.DeviceName == match);
foreach (BluetoothDeviceInfo btdi in peers)
{
Console.WriteLine(btdi.DeviceName);
}
if (device == null)
{
Console.WriteLine(Name +": Not Found");
return false;
}
else
{
Console.WriteLine(Name +": Found");
return true;
}
}
}
}
I am using Sockets in order to communicate with the Bluetooth device.
Its very important to release any resources when disconnecting.
In order to find your COM port you can use this link
Your stream is located here:
System.Net.Sockets.NetworkStream stream = bthClient.GetStream();
Example to how to connect and find your device.
private InTheHand.Net.Sockets.BluetoothClient _BTClient = null;
private InTheHand.Net.Sockets.BluetoothDeviceInfo[] _clientDevices;
/// <summary>
/// Thread function to discover devices
/// </summary>
private void DiscoverBluetoothThread()
{
try
{
_BTClient = new InTheHand.Net.Sockets.BluetoothClient();
_clientDevices = _BTClient.DiscoverDevices(999, _authenticated, _remembered, _unknown);
_BTClient.Dispose();
_BTClient = null;
}
catch (Exception) { }
}
Private void Connect(InTheHand.Net.Sockets.BluetoothDeviceInfo info)
{
string addressN = info.DeviceAddress.ToString("N"); //Format Example: "00066606E014"
string addressC = info.DeviceAddress.ToString("C"); //Format Example: "00:06:66:06:E0:14"
string addressP = info.DeviceAddress.ToString("P"); //Format Example: "00.06.66.06.E0.14"
string addressD = info.DeviceAddress.ToString(); //Format Example: "00066606E014"
string serialPort = FindBluetoothPortName(addressN);
//https://stackoverflow.com/questions/26439091/how-to-get-bluetooth-device-com-serial-port-in-winform-c/27919129#27919129
if (string.IsNullOrEmpty(serialPort) == false && serialPort.Trim().Length > "COM".Length)
bool installed = InstallBluetoothDevice(addressC, passKey, autoConnect);
}
public bool InstallBluetoothDevice(string deviceMACAddress, string passKey, bool connect)
{
string strDevicePassKey = passKey;
string BTMac = deviceMACAddress;
InTheHand.Net.BluetoothAddress BTAddress;
InTheHand.Net.Sockets.BluetoothClient BTClient = new InTheHand.Net.Sockets.BluetoothClient();
InTheHand.Net.BluetoothEndPoint BTEndPoint;
InTheHand.Net.Bluetooth.BluetoothRadio BTRadio;
BTRadio = InTheHand.Net.Bluetooth.BluetoothRadio.PrimaryRadio;
BTRadio.Mode = RadioMode.Connectable;
Guid spguid = BluetoothService.SerialPort;
BTAddress = InTheHand.Net.BluetoothAddress.Parse(BTMac);
BTEndPoint = new InTheHand.Net.BluetoothEndPoint(BTAddress, spguid);
try
{
BluetoothSecurity.PairRequest(BTAddress, strDevicePassKey);
//Application.DoEvents();
BTClient = new InTheHand.Net.Sockets.BluetoothClient();
if (connect)
{
BTClient.Connect(BTEndPoint);
BTEndPoint = new InTheHand.Net.BluetoothEndPoint(BTAddress, spguid);
_connectedDevices.Add(BTAddress, BTClient);
return BTClient.Connected;
}
return true;
}
catch (Exception ex)
{
return false;
}
}
Related
I have 2 Application in a visual studio Windows Forms App(.Net Framework 4) The names of my two programs are:
IpServer
IpClient
My problem is that I do not know what to do that when the IpClient Application closes or stops or the IpServer Application shows a message in messagebox.show("Client Is dissconnect")
IpServer Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace IpServer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
TcpListener tcplist;
Socket s;
private void init()
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
tcplist = new TcpListener(ip,5050);
tcplist.Start();
while (true)
{
s = tcplist.AcceptSocket();
Thread t = new Thread(new ThreadStart(replay));
t.IsBackground = true;
t.Start();
}
}
private void replay()
{
Socket sc = s;
NetworkStream ns = new NetworkStream(sc);
StreamReader reader = new StreamReader(ns);
StreamWriter writer = new StreamWriter(ns);
string str = "";
string response = "";
try { str = reader.ReadLine(); }
catch { str = "error"; }
if (str == "register")
{
MessageBox.Show("ok");
}
response = "registeredSucss,";
writer.WriteLine(response);
writer.Flush();
ns.Close();
sc.Close();
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(init));
t.IsBackground = true;
t.Start();
MessageBox.Show("Server run!!");
button1.Enabled = false;
}
and IpClient Code :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace IpClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
TcpClient tcp;
NetworkStream ns;
StreamReader reader;
StreamWriter writer;
string str = "";
private void button1_Click(object sender, EventArgs e)
{
try
{
tcp = new TcpClient("127.0.0.1",5050);
tcp.ReceiveBufferSize = 25000;
tcp.NoDelay = true;
ns = tcp.GetStream();
reader = new StreamReader(ns);
writer = new StreamWriter(ns);
writer.WriteLine("register");
writer.Flush();
str = reader.ReadLine();
string[] strsplit = null;
strsplit = str.Split(',');
if (strsplit[0] != "registeredSucss")
{
MessageBox.Show("Not connected");
}
else
{
MessageBox.Show("Your connected");
}
}
catch
{
MessageBox.Show("error");
}
}
I wrote a complete example for you.
You can modify it according to your needs.
Simply connecting the client to the server without sending or receiving messages will not disconnect.
In the server and the client, there is a thread that continuously calls the receive function, and sends a message when the connection is disconnected.
byte[] buffer = new byte[1024 * 1024 * 2];
int length = socket.Receive(buffer);
if (length == 0) {
///Write the desired operation
}
"Disconnect when closing the window" uses the formclosing event:
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
}
This is the control diagram used by the two windows:
IpClient:
IpServe:
This is the code for the two windows:
IpClient:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace IpClient {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
Socket socket;//The socket responsible for the connection
private void ConnectB_Click(object sender, EventArgs e) {
//Determine whether to request a connection repeatedly
try {
Log("Connected " + socket.LocalEndPoint.ToString() + "\nPlease do not request the connection repeatedly");
} catch {
//Determine whether the input is wrong
try {
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Create IP address and port number;
IPAddress ip = IPAddress.Parse(Ipbox.Text);
int port = Convert.ToInt32(PortBox.Text);
IPEndPoint iPEndPoint = new IPEndPoint(ip, port);
//Determine whether you can connect to the server
try {
socket.Connect(iPEndPoint);
Log("Connected " + socket.LocalEndPoint.ToString());
//Start receiving data thread
Thread th = new Thread(receive);
th.IsBackground = true;
th.Start();
} catch {
Log("Port is not open");
}
} catch {
socket = null;
Log("Input error");
}
}
}
private void Log(string str) {
ClientLog.AppendText(str + "\r\n");
}
private void receive() {
while (true) {
//Determine whether the data can be received
try {
byte[] buffer = new byte[1024 * 1024 * 2];
int length = socket.Receive(buffer);
if (length == 0) {
Log("Port is not open");
CloseSocket(socket);
socket = null;
break;
}
string txt = Encoding.UTF8.GetString(buffer, 0, length);
Log(socket.RemoteEndPoint + ":\r\t" + txt);
} catch {
break;
}
}
}
private void Form1_Load(object sender, EventArgs e) {
Control.CheckForIllegalCrossThreadCalls = false;
}
private void CloseB_Click(object sender, EventArgs e) {
if (socket != null) {
CloseSocket(socket);
socket = null;
Log("Connection closed");
} else {
Log("Not connected");
}
}
private void SendB_Click(object sender, EventArgs e) {
try {
string txt = SendText.Text;
byte[] buffer = Encoding.ASCII.GetBytes(txt);//ascii encoding
socket.Send(buffer);
} catch {
Log("Not connected");
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
if (socket != null) {
CloseSocket(socket);
socket = null;
}
}
//Disconnect socket
private void CloseSocket(Socket o) {
try {
o.Shutdown(SocketShutdown.Both);
o.Disconnect(false);
o.Close();
} catch {
Log("error");
}
}
}
}
IpServer:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace IpServer {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
Socket socketSend;//Socket responsible for communication
Socket socketListener;//Socket responsible for monitoring
Dictionary<string, Socket> dictionary = new Dictionary<string, Socket>();//Store the connected Socket
private void listnerB_Click(object sender, EventArgs e) {
//Create a listening socket
//SocketType.Stream streaming corresponds to the tcp protocol
//Dgram, datagram corresponds to UDP protocol
socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try {
//Create IP address and port number;
IPAddress ip = IPAddress.Parse(Ipbox.Text);
int port = Convert.ToInt32(PortBox.Text);
IPEndPoint iPEndPoint = new IPEndPoint(ip, port);
//Let the listening socket bind the ip and port number
socketListener.Bind(iPEndPoint);
Log("Listen successfully" + ip + "\t" + port);
//Set up the listening queue
socketListener.Listen(10);//Maximum number of connections at a time
Thread thread = new Thread(Listen);
thread.IsBackground = true;
thread.Start(socketListener);
} catch {
Log("Failed to listen");
}
}
//Use threads to receive data
private void Listen(object o) {
Socket socket = o as Socket;
while (true) {
//The socket responsible for monitoring is used to receive client connections
try {
//Create a socket responsible for communication
socketSend = socket.Accept();
dictionary.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
clientCombo.Items.Add(socketSend.RemoteEndPoint.ToString());
clientCombo.SelectedIndex = clientCombo.Items.IndexOf(socketSend.RemoteEndPoint.ToString());
Log("Connected " + socketSend.RemoteEndPoint.ToString());
//Start a new thread to receive information from the client
Thread th = new Thread(receive);
th.IsBackground = true;
th.Start(socketSend);
} catch {
continue;
}
}
}
//The server receives the message from the client
private void receive(object o) {
Socket socketSend = o as Socket;
while (true) {
//Try to connect to the client
try {
//After the client connects successfully, the server receives the message from the client
byte[] buffer = new byte[1024 * 1024 * 2];//2M大小
//Number of valid bytes received
int length = socketSend.Receive(buffer);
if (length == 0) {
string tmpIp = socketSend.RemoteEndPoint.ToString();
Log(tmpIp + " Offline");
clientCombo.Items.Remove(tmpIp);
//Try to delete the connection information
try {
clientCombo.SelectedIndex = 0;
} catch {
clientCombo.Text = null;
}
CloseSocket(dictionary[tmpIp]);
dictionary.Remove(tmpIp);
break;
}
string str = Encoding.ASCII.GetString(buffer, 0, length);
Log(socketSend.RemoteEndPoint.ToString() + "\n\t" + str);
} catch {
break;
}
}
}
private void Log(string str) {
ServerLog.AppendText(str + "\r\n");
}
private void Form1_Load(object sender, EventArgs e) {
//Cancel errors caused by cross-thread calls
Control.CheckForIllegalCrossThreadCalls = false;
}
//Send a message
private void SendB_Click(object sender, EventArgs e) {
string txt = SendText.Text;
byte[] buffer = Encoding.UTF8.GetBytes(txt);
try {
string ip = clientCombo.SelectedItem.ToString();//Get the selected ip address
Socket socketsend = dictionary[ip];
socketsend.Send(buffer);
} catch{
Log("Transmission failed");
}
}
private void Close_Click(object sender, EventArgs e) {
try {
try {
string tmpip = socketSend.RemoteEndPoint.ToString();
CloseSocket(dictionary[tmpip]);
dictionary.Remove(tmpip);
clientCombo.Items.Remove(tmpip);
try {
clientCombo.SelectedIndex = 0;
} catch {
clientCombo.Text = null;
}
socketSend.Close();
Log(socketSend.RemoteEndPoint.ToString() + "Offline");
socketListener.Close();
Log("Listener is closed");
} catch{
socketListener.Close();
Log("Listener is closed");
}
} catch {
Log("close error");
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
try {
try {
string tmpip = socketSend.RemoteEndPoint.ToString();
CloseSocket(dictionary[tmpip]);
dictionary.Remove(tmpip);
clientCombo.Items.Remove(tmpip);
try {
clientCombo.SelectedIndex = 0;
} catch {
clientCombo.Text = null;
}
socketSend.Close();
socketListener.Close();
} catch {
socketListener.Close();
}
} catch {
}
}
private void CloseSocket(Socket o) {
try {
o.Shutdown(SocketShutdown.Both);
o.Disconnect(false);
o.Close();
} catch {
Log(o.ToString() + "error");
}
}
}
}
OutPut:
Closing the window causes disconnection:
Disconnect manually:
Transfer data:
If you have any question about my code, please add a comment below.
I use windows 7 and C#, .net4.6.1 in VS2017. I used bluetooth CSR 4.0 dongle and csr hormony bluetooth stack as the third party Bluetooth drivers..
I followed this to write a hcitool program :
Looking to write Bluetooth 'hcitool' equivelant in Windows
But when I tried to run the program to connect the BLE device. error occurs at this line
var dev = new BluetoothDeviceInfo(_searchAddress);
The error is : No supported bluetooth protocol stack found.
I have double checked and the parameters I pass is right(info + the device address)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using InTheHand.Net.Bluetooth;
using InTheHand.Net;
using InTheHand.Net.Sockets;
using System.Diagnostics;
using System.Net.Sockets;
namespace hcitool
{
partial class Program
{
static bool infoRatherThanName;
static BluetoothAddress _searchAddress;
static int Main(string[] args)
{
if (args.Length < 1) {
Console.WriteLine("Please specify command.");
return 2;
}
var cmd = args[0];
switch (cmd) {
case "name":
infoRatherThanName = false;
break;
case "info":
infoRatherThanName = true;
break;
//-
case "dev":
return ShowRadios();
//case "auth":
// return CauseAuth(GETADDRESS());
default:
throw new NotImplementedException("Command: '" + cmd + "'");
}
if (args.Length < 2) {
Console.WriteLine("Please specify device address.");
return 2;
}
var addrS = args[1];
_searchAddress = BluetoothAddress.Parse(addrS);
//
var dev = new BluetoothDeviceInfo(_searchAddress);
bool isInRange = GetCanConnectTo(dev);
if (isInRange) {
PrintDevice(dev);
} else {
Console.WriteLine("Can't see that device.");
}
//
Console.WriteLine("simple");
return Simple();
//return Fancier();
}
//----
private static int ShowRadios()
{
BluetoothRadio[] list;
try {
list = BluetoothRadio.AllRadios;
} catch (Exception) {
return 1;
}
Debug.Assert(list.Length != 0, "Expect zero radios case to raise an error.");
foreach (var curR in list) {
Console.WriteLine("* {0} '{1}'", curR.LocalAddress, curR.Name);
Console.WriteLine("{0}", curR.SoftwareManufacturer);
Console.WriteLine("{0}", curR.Manufacturer);
Console.WriteLine("{0}", curR.Mode);
}//for
return 0;
}
private static int CauseAuth(BluetoothAddress addr)
{
BluetoothSecurity.PairRequest(addr, null);
return 0;
}
//----
static int Simple()
{
BluetoothDeviceInfo[] devices;
BluetoothDeviceInfo foundDev = null;
var cli = new BluetoothClient();
// Fast: Remembered/Authenticated
devices = cli.DiscoverDevices(255, true, true, false, false);
SimpleCheckDevice(devices, ref foundDev);
if (foundDev == null) {
// Slow: Inquiry
cli.DiscoverDevices(255, false, false, true, false);
SimpleCheckDevice(devices, ref foundDev);
}
//
if (foundDev != null) {
return 0;
} else {
return 1;
}
}
private static void SimpleCheckDevice(IEnumerable<BluetoothDeviceInfo> devices,
ref BluetoothDeviceInfo foundDev)
{
foreach (var cur in devices) {
if (cur.DeviceAddress == _searchAddress) {
foundDev = cur;
PrintDevice(cur);
}
}//for
}
private static void PrintDevice(BluetoothDeviceInfo cur)
{
Console.WriteLine("* Found device: '{0}' ", cur.DeviceName);
if (infoRatherThanName) {
try {
var vs = cur.GetVersions();
Console.WriteLine(vs.Manufacturer);
Console.WriteLine(vs.LmpVersion);
Console.WriteLine(vs.LmpSubversion);
Console.WriteLine(vs.LmpSupportedFeatures);
} catch (Exception ex) {
Console.WriteLine("Failed to get remote device versions info: "
+ ex.Message);
}
}
}
//----
private static bool GetCanConnectTo(BluetoothDeviceInfo device)
{
bool inRange;
Guid fakeUuid = new Guid("{F13F471D-47CB-41d6-9609-BAD0690BF891}");
try {
ServiceRecord[] records = device.GetServiceRecords(fakeUuid);
Debug.Assert(records.Length == 0, "Why are we getting any records?? len: " + records.Length);
inRange = true;
} catch (SocketException) {
inRange = false;
}
return inRange;
}
}
}
I had a perfectly fine working console program that uses UdpClient.send to send messages to another program on the localhost (over port 7777). (which oddly enough is an almost identical version this C# script, but running in unity3d, and it has no trouble receiving with the same code).
Now I need to get replies from that program. I added a thread (see bottom) which listens on port 7778 for messages. But I am getting an error when starting saying that:
An existing connection was forcibly closed by the remote host
using Newtonsoft.Json;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Blaster
{
class Blaster
{
UdpClient client;
IPEndPoint outPoint;
IPEndPoint inPoint;
public int oPort = 7777;
public int iPort = 7778;
public string hostName = "localhost";
public int stepNum = 0;
const int rate = 1000;
public System.Timers.Timer clock;
Thread listener;
static void Main(string[] args)
{
Blaster b = new Blaster();
b.run();
}
Blaster()
{
client = new UdpClient();
outPoint = new IPEndPoint(Dns.GetHostAddresses(hostName)[0], oPort);
inPoint = new IPEndPoint(Dns.GetHostAddresses(hostName)[0], iPort);
}
void run()
{
this.stepNum = 0;
listener = new Thread(new ThreadStart(translater));
listener.IsBackground = true;
listener.Start();
Console.WriteLine("Press Enter to do a send loop...\n");
Console.ReadLine();
Console.WriteLine("started at {0:HH:mm:ss.fff}", DateTime.Now);
start();
Console.WriteLine("Press Enter to stop");
Console.ReadLine();
stop();
client.Close();
}
void stop()
{
clock.Stop();
clock.Dispose();
}
void start()
{
clock = new System.Timers.Timer(rate);
clock.Elapsed += send;
clock.AutoReset = true;
clock.Enabled = true;
}
void send(Object source, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("sending: {0}", stepNum);
Byte[] sendBytes = Encoding.ASCII.GetBytes(message());
try
{
client.Send(sendBytes, sendBytes.Length, outPoint);
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
string message()
{
Packet p = new Packet();
p.id = "car";
p.start = DateTime.Now;
p.x = 1.2f;
p.y = 0.4f;
p.z = 4.5f;
p.step = stepNum++;
string json = JsonConvert.SerializeObject(p);
return json;
}
void translater()
{
Byte[] data = new byte[0];
client.Client.Bind(inPoint);
while (true)
{
try
{
data = client.Receive(ref inPoint);
}
catch (Exception err)
{
Console.WriteLine("Blaster.translater: recieve data error: " + err.Message);
client.Close();
return;
}
string json = Encoding.ASCII.GetString(data);
Console.WriteLine(json);
Packet p = JsonConvert.DeserializeObject<Packet>(json);
}
}
}
}
Ok, I had seen some examples of folks using a single client object for both send and receive (as well as the same port). But then I saw a different port was needed if they were on the same host. Now I see you need a separate udpClient.
using Newtonsoft.Json;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Blaster
{
class Blaster
{
UdpClient client;
IPEndPoint outPoint;
IPEndPoint inPoint;
public int oPort = 7777;
public int iPort = 7778;
public string hostName = "localhost";
public int stepNum = 0;
const int rate = 1000;
public System.Timers.Timer clock;
Thread listener;
static void Main(string[] args)
{
Blaster b = new Blaster();
b.run();
}
Blaster()
{
client = new UdpClient();
outPoint = new IPEndPoint(Dns.GetHostAddresses(hostName)[0], oPort);
inPoint = new IPEndPoint(Dns.GetHostAddresses(hostName)[0], iPort);
}
void run()
{
this.stepNum = 0;
listener = new Thread(new ThreadStart(translater));
listener.IsBackground = true;
listener.Start();
Console.WriteLine("Press Enter to do a send loop...\n");
Console.ReadLine();
Console.WriteLine("started at {0:HH:mm:ss.fff}", DateTime.Now);
start();
Console.WriteLine("Press Enter to stop");
Console.ReadLine();
stop();
client.Close();
}
void stop()
{
clock.Stop();
clock.Dispose();
}
void start()
{
clock = new System.Timers.Timer(rate);
clock.Elapsed += send;
clock.AutoReset = true;
clock.Enabled = true;
}
void send(Object source, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("sending: {0}", stepNum);
Byte[] sendBytes = Encoding.ASCII.GetBytes(message());
try
{
client.Send(sendBytes, sendBytes.Length, outPoint);
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
string message()
{
Packet p = new Packet();
p.id = "car";
p.start = DateTime.Now;
p.x = 1.2f;
p.y = 0.4f;
p.z = 4.5f;
p.step = stepNum++;
string json = JsonConvert.SerializeObject(p);
return json;
}
void translater()
{
UdpClient server = new UdpClient();
Byte[] data = new byte[0];
server.Client.Bind(inPoint);
while (true)
{
try
{
data = server.Receive(ref inPoint);
}
catch (Exception err)
{
Console.WriteLine("Blaster.translater: recieve data error: " + err.Message);
client.Close();
return;
}
string json = Encoding.ASCII.GetString(data);
Console.WriteLine(json);
Packet p = JsonConvert.DeserializeObject<Packet>(json);
}
}
}
}
I want my computer to be a bluetooth server, handlig at least 100 connections from smartphones simultaneously. This is the idea:
I start the server and it begin to listen for connections. For each connection it should store the mac adress of the device. Each device should be able to send messages to the server and vice versa.
I've been searching a lot but didnt find a certain way.
How to listen for connections and handle them? Store in array? Start A Thread?
I've been able to start a 1 client server, but coudnt evolve it.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Ports;
using InTheHand.Net.Sockets;
using System.IO;
namespace BluetoothChamada
{
public partial class Form1 : Form
{
List<string> items;
String clientConectedName, clientConectedMAC;
public Form1()
{
InitializeComponent();
items = new List<string>();
}
private void bGo_Click(object sender, EventArgs e)
{
if (serverStarted)
{
updateUI("---Servidor já foi Iniciado---");
return;
}
if (rbServer.Checked)
{
connectAsServer();
}
else
{
Scan();
}
}
private void startScan()
{
listBox1.DataSource = null;
listBox1.Items.Clear();
items.Clear();
Thread bluetoothScanThread = new Thread(new ThreadStart(Scan));
bluetoothScanThread.Start();
}
BluetoothDeviceInfo[] devices;
private void Scan()
{
updateUI("Procurando dispositivos...");
BluetoothClient client = new BluetoothClient();
devices = client.DiscoverDevicesInRange();
updateUI("Procura finalizada");
updateUI(devices.Length.ToString() + " dispositivos encontrados");
foreach (BluetoothDeviceInfo d in devices)
{
items.Add(d.DeviceName);
}
updateDeviceList();
}
private void connectAsServer()
{
Thread bluetoothServerThread = new Thread(new ThreadStart(ServerConnectThread));
bluetoothServerThread.Start();
}
Guid mUUID = new Guid("00001101-0000-1000-8000-00805F9B34FB");
bool serverStarted = false;
public void ServerConnectThread()
{
serverStarted = true;
BluetoothListener blueListener = new BluetoothListener(mUUID);
blueListener.Start();
updateUI("---Servidor Iniciado, aguardando clientes---\r\n\n");
BluetoothClient connection = blueListener.AcceptBluetoothClient();
getData();
updateUI("Cliente: " + clientConectedName + "\r\nMac: " + clientConectedMAC);
Stream mStream = connection.GetStream();
while (true)
{
try
{
byte[] received = new byte[1024];
mStream.Read(received, 0, received.Length);
updateUI(System.Environment.NewLine + "Recebido: " + Encoding.ASCII.GetString(received));
byte[] sent = Encoding.ASCII.GetBytes("FeedBack: OK \r\n");
mStream.Write(sent, 0, sent.Length);
}
catch (IOException exception)
{
updateUI("Cliente foi desconectado");
break;
}
}
}
private void getData()
{
BluetoothClient client = new BluetoothClient();
BluetoothDeviceInfo[] devices = client.DiscoverDevices();
foreach (BluetoothDeviceInfo device in devices)
{
if (!device.Connected)
{
}
else
{
clientConectedName = device.DeviceName;
clientConectedMAC = device.DeviceAddress.ToString();
}
}
}
private void updateUI(string message)
{
Func<int> del = delegate()
{
tbOutput.AppendText(message + System.Environment.NewLine);
return 0;
};
Invoke(del);
}
private void updateDeviceList()
{
Func<int> del = delegate()
{
listBox1.DataSource = items;
return 0;
};
Invoke(del);
}
}
}
I am having an issue with my IRC Bot I am trying to write in c# just as a way to help get my head around the IRC protocol, I am planning on writing a client/server in the future but as you can prolly guess I am far off this :P
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
namespace LolBot
{
struct IRCConfig
{
public string server;
public int port;
public string nick;
public string name;
}
class IRCBot
{
TcpClient IRCConnection = null;
IRCConfig config;
NetworkStream ns = null;
StreamReader sr = null;
StreamWriter sw = null;
public IRCBot(IRCConfig config)
{
this.config = config;
try
{
IRCConnection = new TcpClient(config.server, config.port);
}
catch
{
Console.WriteLine("Connection Error");
}
try
{
ns = IRCConnection.GetStream();
sr = new StreamReader(ns);
sw = new StreamWriter(ns);
sendData("USER", config.nick + config.name);
sendData("NICK", config.nick);
}
catch
{
Console.WriteLine("Communication error");
}
finally
{
if (sr != null)
sr.Close();
if (sw != null)
sw.Close();
if (ns != null)
ns.Close();
if (IRCConnection != null)
IRCConnection.Close();
}
}
public void sendData(string cmd, string param)
{
if (param == null)
{
sw.WriteLine(cmd);
sw.Flush();
Console.WriteLine(cmd);
}
else
{
sw.WriteLine(cmd + " " + param);
sw.Flush();
Console.WriteLine(cmd + " " + param);
}
}
public void IRCWork()
{
string[] ex;
string data;
bool shouldRun = true;
while (shouldRun)
{
data = sr.ReadLine();
Console.WriteLine(data);
char[] charSeparator = new char[] { ' ' };
ex = data.Split(charSeparator, 5);
if (ex[0] == "PING")
{
sendData("PONG", ex[1]);
}
if (ex.Length > 4) //is the command received long enough to be a bot command?
{
string command = ex[3]; //grab the command sent
switch (command)
{
case ":!join":
sendData("JOIN", ex[4]); //if the command is !join send the "JOIN" command to the server with the parameters set by the user
break;
case ":!say":
sendData("PRIVMSG", ex[2] + " " + ex[4]); //if the command is !say, send a message to the chan (ex[2]) followed by the actual message (ex[4]).
break;
case ":!quit":
sendData("QUIT", ex[4]); //if the command is quit, send the QUIT command to the server with a quit message
shouldRun = false; //turn shouldRun to false - the server will stop sending us data so trying to read it will not work and result in an error. This stops the loop from running and we will close off the connections properly
break;
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
IRCConfig conf = new IRCConfig();
conf.name = "LolBot";
conf.nick = "LolBot";
conf.port = 6667;
conf.server = "irc.strictfp.com";
new IRCBot(conf);
Console.WriteLine("Bot quit/crashed");
Console.ReadLine();
}
}
}
Whenever I execute the Bot, it comes up with:
USER AspiBot google.com google.com :AspiBot
NICK AspiBot
Bot quit/crashed
I don't really understand why it is quiting before connecting to the server and I am also looking on how to set it up to join a channel, I am aware that I need to use JOIN but I'm not sure how to implent it.
You should probably not do so much in the constructor, but the problem you are encountering here is that you are not calling IRCWork() after newing up the bot.
var bot = new IRCBot(conf);
bot.IRCWork();
EDIT You are also closing all of your connections in the finally block of your constructor, so IRCWork() isn't going to work anyway. Try implementing IDisposable, and putting your close logic in Dispose():
using (var bot = new IRCBot(conf))
{
bot.IRCWork();
}
Quick refactor of posted code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
namespace LolBot
{
internal struct IRCConfig
{
public string server;
public int port;
public string nick;
public string name;
}
internal class IRCBot : IDisposable
{
private TcpClient IRCConnection = null;
private IRCConfig config;
private NetworkStream ns = null;
private StreamReader sr = null;
private StreamWriter sw = null;
public IRCBot(IRCConfig config)
{
this.config = config;
}
public void Connect()
{
try
{
IRCConnection = new TcpClient(config.server, config.port);
}
catch
{
Console.WriteLine("Connection Error");
throw;
}
try
{
ns = IRCConnection.GetStream();
sr = new StreamReader(ns);
sw = new StreamWriter(ns);
sendData("USER", config.nick + config.name);
sendData("NICK", config.nick);
}
catch
{
Console.WriteLine("Communication error");
throw;
}
}
public void sendData(string cmd, string param)
{
if (param == null)
{
sw.WriteLine(cmd);
sw.Flush();
Console.WriteLine(cmd);
}
else
{
sw.WriteLine(cmd + " " + param);
sw.Flush();
Console.WriteLine(cmd + " " + param);
}
}
public void IRCWork()
{
string[] ex;
string data;
bool shouldRun = true;
while (shouldRun)
{
data = sr.ReadLine();
Console.WriteLine(data);
char[] charSeparator = new char[] {' '};
ex = data.Split(charSeparator, 5);
if (ex[0] == "PING")
{
sendData("PONG", ex[1]);
}
if (ex.Length > 4) //is the command received long enough to be a bot command?
{
string command = ex[3]; //grab the command sent
switch (command)
{
case ":!join":
sendData("JOIN", ex[4]);
//if the command is !join send the "JOIN" command to the server with the parameters set by the user
break;
case ":!say":
sendData("PRIVMSG", ex[2] + " " + ex[4]);
//if the command is !say, send a message to the chan (ex[2]) followed by the actual message (ex[4]).
break;
case ":!quit":
sendData("QUIT", ex[4]);
//if the command is quit, send the QUIT command to the server with a quit message
shouldRun = false;
//turn shouldRun to false - the server will stop sending us data so trying to read it will not work and result in an error. This stops the loop from running and we will close off the connections properly
break;
}
}
}
}
public void Dispose()
{
if (sr != null)
sr.Close();
if (sw != null)
sw.Close();
if (ns != null)
ns.Close();
if (IRCConnection != null)
IRCConnection.Close();
}
}
internal class Program
{
private static void Main(string[] args)
{
IRCConfig conf = new IRCConfig();
conf.name = "LolBot";
conf.nick = "LolBot";
conf.port = 6667;
conf.server = "irc.strictfp.com";
using (var bot = new IRCBot(conf))
{
bot.Connect();
bot.IRCWork();
}
Console.WriteLine("Bot quit/crashed");
Console.ReadLine();
}
}
}