Bluetooth connection from phone to PC C# Xamarin.Forms - c#

Good day developers! I'm currently working on a project that requires a bluetooth connection from a phone to the computer and transmit some data and output it on PuTTY. But the problem is whenever I want connect with the socket it gives me this error:
read failed, socket might closed or timeout, read ret: -1
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Android.App;
using Android.Bluetooth;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using BluetoothSample.Droid.PlatformSpecifics;
using BluetoothSample.Services.Interfaces;
using Java.Util;
using Xamarin.Forms;
using Debug = System.Diagnostics.Debug;
[assembly: Dependency(typeof(BluetoothService))]
namespace BluetoothSample.Droid.PlatformSpecifics
{
public class BluetoothService : IBluetoothService
{
private CancellationTokenSource _cancellationToken { get; }
public string MessageToSend { get; set; }
public BluetoothService()
{
_cancellationToken = new CancellationTokenSource();
}
public void Connect(string name)
{
Task.Run(async () => await ConnectDevice(name));
}
private async Task ConnectDevice(string name)
{
BluetoothDevice device = null;
BluetoothAdapter adapter = BluetoothAdapter.DefaultAdapter;
BluetoothSocket bthSocket = null;
while (_cancellationToken.IsCancellationRequested == false)
{
try
{
Thread.Sleep(250);
adapter = BluetoothAdapter.DefaultAdapter;
if (adapter == null)
Debug.Write("No bluetooth adapter found!");
else
Debug.Write("Adapter found!");
if (!adapter.IsEnabled)
Debug.Write("Bluetooth adapter is not enabled.");
else
Debug.Write("Adapter found!");
Debug.Write("Try to connect to " + name);
foreach (var bondedDevice in adapter.BondedDevices)
{
Debug.Write("Paired devices found: " + bondedDevice.Name.ToUpper());
if (bondedDevice.Name.ToUpper().IndexOf(name.ToUpper()) >= 0)
{
Debug.Write("Found " + bondedDevice.Name + ". Try to connect with it!");
device = bondedDevice;
break;
}
}
if (device == null)
Debug.Write("Named device not found.");
else
{
UUID uuid = UUID.FromString("00001101-0000-1000-8000-00805f9b34fb");
bthSocket = device.CreateRfcommSocketToServiceRecord(uuid);
if (bthSocket != null)
{
adapter.CancelDiscovery();
await bthSocket.ConnectAsync();
if (bthSocket.IsConnected)
{
Debug.Write("Connected");
while (_cancellationToken.IsCancellationRequested == false)
{
if (MessageToSend != null)
{
var chars = MessageToSend.ToCharArray();
var bytes = new List<byte>();
foreach (var character in chars)
{
bytes.Add((byte)character);
}
await bthSocket.OutputStream.WriteAsync(bytes.ToArray(), 0, bytes.Count);
MessageToSend = null;
}
}
}
}
}
}
catch (Exception ex)
{
Debug.Write(ex);
Debug.Write(ex.Message);
}
finally
{
if (bthSocket != null)
bthSocket.Close();
device = null;
adapter = null;
}
}
}
public void Disconnect()
{
if (_cancellationToken != null)
{
_cancellationToken.Cancel();
}
}
public List<string> PairedDevices()
{
BluetoothAdapter adapter = BluetoothAdapter.DefaultAdapter;
List<string> devices = new List<string>();
foreach (var bondedDevices in adapter.BondedDevices)
devices.Add(bondedDevices.Name);
return devices;
}
public void Send(string message)
{
if (MessageToSend == null)
MessageToSend = message;
}
}
}

Ok so I solved my problem by replacing my ConnectDevice() function by this block of code:
private async Task ConnectDevice(string name)
{
BluetoothDevice device = null;
BluetoothAdapter adapter = BluetoothAdapter.DefaultAdapter;
BluetoothSocket bthSocket = null;
BluetoothServerSocket bthServerSocket = null;
UUID uuid = UUID.FromString("00001101-0000-1000-8000-00805f9b34fb");
bthServerSocket = adapter.ListenUsingRfcommWithServiceRecord("TLCI Barcode Scanner", uuid);
_cancellationToken = new CancellationTokenSource();
while (_cancellationToken.IsCancellationRequested == false)
{
try
{
Thread.Sleep(250);
adapter = BluetoothAdapter.DefaultAdapter;
if (adapter == null)
Debug.Write("No bluetooth adapter found!");
else
Debug.Write("Adapter found!");
if (!adapter.IsEnabled)
Debug.Write("Bluetooth adapter is not enabled.");
else
Debug.Write("Adapter found!");
Debug.Write("Try to connect to " + name);
foreach (var bondedDevice in adapter.BondedDevices)
{
Debug.Write("Paired devices found: " + bondedDevice.Name.ToUpper());
if (bondedDevice.Name.ToUpper().IndexOf(name.ToUpper()) >= 0)
{
Debug.Write("Found " + bondedDevice.Name + ". Try to connect with it!");
device = bondedDevice;
Debug.Write(bondedDevice.Type.ToString());
break;
}
}
if (device == null)
Debug.Write("Named device not found.");
else
{
bthSocket = bthServerSocket.Accept();
adapter.CancelDiscovery();
if (bthSocket != null)
{
Debug.Write("Connected");
if (bthSocket.IsConnected)
{
var mReader = new InputStreamReader(bthSocket.InputStream);
var buffer = new BufferedReader(mReader);
while (_cancellationToken.IsCancellationRequested == false)
{
if (MessageToSend != null)
{
var chars = MessageToSend.ToCharArray();
var bytes = new List<byte>();
foreach (var character in chars)
{
bytes.Add((byte)character);
}
await bthSocket.OutputStream.WriteAsync(bytes.ToArray(), 0, bytes.Count);
MessageToSend = null;
}
}
}
}
}
}
catch (Exception ex)
{
Debug.Write(ex);
Debug.Write(ex.Message);
}
finally
{
if (bthSocket != null)
bthSocket.Close();
device = null;
adapter = null;
}
}
}
And that's it I'm able to connect my phone into my pc now.

Related

No supported bluetooth protocol stack found

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

Mono HTTPListener throws exception when using self signed SSL certificate

I wrote a little web server on Linux using the Mono HTTPListener class. It works fine for http requests. However, if I use a self-signed SSL certificate (created with openssl and installed with httpcfg) it will throw an un-catchable exception as soon as the request forom a browser comes in.
The exception is:
Unhandled Exception:
System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The client stopped the handshake.
at Mono.Security.Protocol.Tls.SslServerStream.EndNegotiateHandshake (IAsyncResult asyncResult) <0xb4b079c8 + 0x001cf> in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) <0xb4b07428 + 0x0005f> in <filename unknown>:0
Here is the complete code:
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Threading;
namespace SSLTest
{
class MainClass
{
static void Main ()
{
try
{
HttpListener l = new HttpListener ();
l.Prefixes.Add ("https://*:8443/");
l.Start ();
Console.WriteLine("Server is running.");
while (l.IsListening)
{
//create the worker thread
HttpListenerContext ctx = l.GetContext(); //.GetContext() blocks until something comes in
if(ctx != null)
{
if(ctx.Request.RemoteEndPoint != null)
{
Thread workerThread = new Thread(() => RunWorker(ctx));
workerThread.Start();
}
}
}
Console.WriteLine("Server is stopped.");
}
catch(Exception ex)
{
Console.WriteLine ("Exception in Main: " + ex);
}
}
static void RunWorker(HttpListenerContext ctx)
{
try
{
if(ctx.Request != null)
{
if(ctx.Request.RemoteEndPoint != null)
{
Console.WriteLine ("Got request from " + ctx.Request.RemoteEndPoint.ToString());
string rstr = "Test Website!\n" + DateTime.Now.ToString();
byte[] buf = Encoding.UTF8.GetBytes(rstr);
if(buf!=null)
{
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
}
}
}
catch(Exception ex)
{
Console.WriteLine ("#Exception in RunWorker: " + ex.Message);
}
}
}
}
This is the case when I am using a browser for the first time. The browser will show something like "Unsafe certificate! Do you want to continue (not recommended)?". If I click on Yes and restart the crashed server app it will work from that moment on.
How can I fix this?
Also, I am not able to catch this exception with a try block. It will always terminate my application. How can I prevent that?
Should be fixed by an unreleased bug fix https://bugzilla.xamarin.com/show_bug.cgi?id=52675... although I have not had a chance to test.
I have seen this as well and am currently trying to find a way to handle the exception. This looks to be a bug in Mono.
It occurs when certificate verification fails in any way.
I obtained a CA signed cert which fixed the problem as long as the certificate common name (dns) is the same as the dns used in the URL I'm trying to send a get request to. If I instead specify the public IP address in the url (which the cert is not registered with) the mono app will crash with an unhandled exception.
One option we're considering is implementing a TCP based webserver which would use a TcpListener instead of the heavy HttpListener which would in turn fix other problems we're seeing with mono httplistener prefixes not working correctly when bound to the internal IP behind a NAT. This would mean the cert could be bound pro-grammatically as well, it just takes more work.
Below is a very rough version of what this might look like. By no means is this a finished product but it may serve to help others on this same path... I'll have to do this in two answers, this is the tcp web server.
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
namespace Example.Lib.Net
{
internal class TcpWebServer : IDisposable
{
private TcpListener m_Listener = null;
private bool m_IsSSL = false;
private X509Certificate2 m_ServerCertificate = null;
internal X509Certificate2 ServerCertificate
{
get { return m_ServerCertificate; }
set { m_ServerCertificate = value; }
}
internal void Start(string ip, int port, bool useSsl = false)
{
if (useSsl) // for player streams always use ssl to
{
m_IsSSL = true;
m_ServerCertificate = new X509Certificate2("./cert/cert.pfx", "pass");
X509Store store = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(m_ServerCertificate);
store.Close();
}
IPAddress ipAddr = IPAddress.Any;
if (ip != "*") IPAddress.TryParse(ip, out ipAddr);
try
{
m_Listener = new TcpListener(ipAddr, port);
m_Listener.Start();
m_Listener.BeginAcceptTcpClient(OnClientAccepted, m_Listener);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
private void OnClientAccepted(IAsyncResult ar)
{
TcpListener listener = ar.AsyncState as TcpListener;
if (listener == null)
return;
TcpClient client = listener.EndAcceptTcpClient(ar);
client.ReceiveBufferSize = 65535;
client.Client.ReceiveBufferSize = 65535;
TcpWebConnection con = new TcpWebConnection(client, this, m_IsSSL);
listener.BeginAcceptTcpClient(OnClientAccepted, listener);
}
}
}
This is the tcp web connection code.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Text;
using System.Threading;
using System.Web;
using Example.Lib.Common;
using Example.Lib.Models;
namespace Example.Lib.Net
{
internal enum RequestType
{
None = 0,
GET = 1,
POST = 2,
OPTIONS = 3
}
internal class TcpWebConnection : IDisposable
{
#region private members
private bool m_IsDisposed = false;
private bool m_IsSSL = false;
private bool m_HasHeaders = false;
private bool m_FileCreated = false;
private bool m_IsFileUpload = false;
private RequestType m_RequestType = RequestType.None;
private string m_ReadData = string.Empty;
private string m_Request = string.Empty;
private string m_RemoteIP = string.Empty;
private string m_AbsoluteURI = string.Empty;
private string m_ContentType = string.Empty;
private string m_TempFilename = string.Empty;
private byte[] m_EndBoundaryBytes = null;
private byte[] m_StartBoundaryBytes = null;
private int m_ContentLength = 0;
private long m_StartBoundaryIndex = -1;
private long m_EndBoundaryIndex = -1;
private long m_BytesRead = 0;
private NameValueCollection m_QueryString = null;
private string[] m_Segments = new string[1];
private string m_HttpVersion = "HTTP/1.1";
private byte[] m_PostData = null;
private byte[] m_Buffer = new byte[65535];
private ReadWriteBuffer m_TempBuffer;
private FileStream m_FileStream = null;
private MemoryStream m_FullBuffer = new MemoryStream();
private TcpClient m_Client = null;
private System.IO.Stream m_NetworkStream = null;
private TcpWebServer m_Parent = null;
private Thread m_Thread_Read = null;
private Timer m_Timer_Check = null;
private DateTime m_LastRead = DateTime.Now;
private AutoResetEvent m_WaitHandle_Write;
#endregion private members
#region constructors
internal TcpWebConnection(TcpClient client, TcpWebServer parent, bool ssl)
{
m_WaitHandle_Write = new AutoResetEvent(false);
m_TempBuffer = new ReadWriteBuffer(65535);
m_IsSSL = ssl;
m_Segments[0] = string.Empty;
m_Client = client;
m_Parent = parent;
m_RemoteIP = ((IPEndPoint)m_Client.Client.RemoteEndPoint).Address.ToString();
if (ssl)
{
m_NetworkStream = new SslStream(m_Client.GetStream(), false);
}
else
{
m_NetworkStream = m_Client.GetStream();
}
m_NetworkStream.ReadTimeout = 2000;
m_Timer_Check = new Timer(Timer_Check_Callback, this, 2000, 2000);
// start threads
m_Thread_Read = new Thread(DoRead);
m_Thread_Read.IsBackground = true;
m_Thread_Read.Start();
}
#endregion constructors
#region destructors
~TcpWebConnection()
{
try
{
if (m_Timer_Check != null) m_Timer_Check.Dispose();
m_Timer_Check = null;
}
catch { } // if the timer was
}
#endregion destructors
#region internal properties
internal bool IsLargeFileUpload { get; set; } = false;
internal string TempFilename
{
get { return m_TempFilename; }
set { m_TempFilename = value; }
}
/// <summary>
/// Remote IP
/// </summary>
internal string RemoteIP
{
get { return m_RemoteIP; }
}
internal string AbsoluteURI
{
get { return m_AbsoluteURI; }
}
internal string ContentType
{
get { return m_ContentType; }
}
internal string[] Segments
{
get { return m_Segments; }
}
internal NameValueCollection QueryString
{
get { return m_QueryString; }
}
internal Stream NetworkStream
{
get { return m_NetworkStream; }
}
internal int ContentLength
{
get { return m_ContentLength; }
}
#endregion internal properties
#region private methods
private void Timer_Check_Callback(object state)
{
if ((DateTime.Now - m_LastRead).TotalSeconds > 15)
{
try
{
Program.BlacklistIP(m_RemoteIP, "TcpWebConnection - Timer", "Connection Timed Out");
ProcessRequest(m_ReadData);
Dispose();
}
catch (Exception e) { }
}
}
private void DoRead()
{
if (m_IsSSL)
{
try
{
((SslStream)m_NetworkStream).AuthenticateAsServer(m_Parent.ServerCertificate, false, SslProtocols.Tls, false);
((SslStream)m_NetworkStream).BeginRead(m_Buffer, 0, m_Buffer.Length, new AsyncCallback(SslRead), m_NetworkStream);
m_NetworkStream.ReadTimeout = 5000;
m_NetworkStream.WriteTimeout = 5000;
}
catch (Exception e)
{
//Console.WriteLine("SSL Auth Error: " + e.Message);
}
}
else
{
NormalRead();
}
}
private void UpdatePostData()
{
m_FullBuffer.Position = 0;
byte[] fullBuffer = Common.Conversion.MemoryStreamToByteArray(m_FullBuffer);
m_FullBuffer.Dispose();
if (m_StartBoundaryIndex > -1 && m_EndBoundaryIndex > -1)
{
m_PostData = new byte[m_EndBoundaryIndex - m_StartBoundaryIndex];
Array.Copy(fullBuffer, m_StartBoundaryIndex, m_PostData, 0, m_EndBoundaryIndex - m_StartBoundaryIndex);
}
}
internal void SaveFile(string filepath)
{
try
{
UpdatePostData();
if (m_PostData == null) return;
if (!Directory.Exists(Path.GetDirectoryName(filepath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(filepath));
}
if (File.Exists(filepath))
{
File.Delete(filepath);
}
using (FileStream output = new FileStream(filepath, FileMode.Create, FileAccess.Write))
{
output.Write(m_PostData, 0, m_PostData.Length);
}
}
catch (Exception e)
{
// report error
}
}
private void AppendBuffer(byte[] newBuffer, int length)
{
// we need to keep a running buffer here, the last 1024 bytes? how best to find the end boundary? need to determine when the stream is finished!
m_TempBuffer.Write(newBuffer, length);
if (m_IsFileUpload)
{
if (m_EndBoundaryIndex < 0)
{
m_EndBoundaryIndex = StreamHelper.LastIndexOf(m_TempBuffer.RawBytes, m_TempBuffer.Count, m_EndBoundaryBytes);
if (!IsLargeFileUpload && m_EndBoundaryIndex > -1)
{
m_EndBoundaryIndex = (m_FullBuffer.Length + length) - (m_TempBuffer.Count - m_EndBoundaryIndex);
}
}
if (m_StartBoundaryIndex < 0)
{
m_StartBoundaryIndex = StreamHelper.IndexOf(m_FullBuffer, m_StartBoundaryBytes);
if (m_StartBoundaryIndex > -1)
{
m_StartBoundaryIndex = StreamHelper.IndexOf(m_FullBuffer, Encoding.UTF8.GetBytes("\r\n\r\n"), m_StartBoundaryIndex + m_StartBoundaryBytes.Length) + 4;
}
}
}
if (m_StartBoundaryIndex == -1 || !IsLargeFileUpload) // if this is not a file upload because no start boundary has been found then write buffer to memory
{
m_FullBuffer.Write(newBuffer, 0, length);
}
else
{
if (!m_FileCreated) // we have never written to the file, dump the contents of the full buffer now
{
bool exists = true;
while (exists)
{
m_TempFilename = Config.StaticConfig.TempFolder + "/" + Path.GetRandomFileName();
exists = File.Exists(m_TempFilename);
}
m_FileStream = new FileStream(m_TempFilename, FileMode.Create, FileAccess.Write);
m_FullBuffer.Position = m_StartBoundaryIndex;
m_FullBuffer.CopyTo(m_FileStream);
m_FileStream.Write(newBuffer, 0, length);
m_FileCreated = true;
}
else // we have previously written to the file, append new bytes
{
if (m_EndBoundaryIndex == -1)
{
m_FileStream.Write(newBuffer, 0, length);
}
else
{
m_FileStream.Write(newBuffer, 0, length - m_EndBoundaryBytes.Length);
}
}
}
}
private void NormalRead()
{
try
{
int bufferSize = m_Buffer.Length;
int bytesRead = m_Client.Client.Receive(m_Buffer, bufferSize, 0);
while (bytesRead > 0 && !m_IsDisposed)
{
m_LastRead = DateTime.Now;
m_BytesRead += bytesRead;
if (!m_HasHeaders || m_RequestType == RequestType.GET)
{
string sBuffer = Encoding.ASCII.GetString(m_Buffer, 0, bytesRead);
m_ReadData += sBuffer;
}
AppendBuffer(m_Buffer, bytesRead);
m_HasHeaders = UpdateUniqueHeaders();
if (!m_HasHeaders && m_BytesRead > 1024)
{
Program.BlacklistIP(m_RemoteIP, m_ReadData, "No HTTP headers found in the first 1024 bytes");
return;
}
if (m_RequestType != RequestType.POST)
{
break; // process the request
}
else if (m_EndBoundaryIndex != -1)
{
break; // process the request, we found our end boundary for posted data
}
bytesRead = m_Client.Client.Receive(m_Buffer, bufferSize, 0);
}
ProcessRequest(m_ReadData);
}
catch (Exception e)
{
// report error
}
}
private void SslRead(IAsyncResult ar)
{
if (m_IsDisposed) return;
try
{
int byteCount = -1;
int bufferSize = m_Buffer.Length;
m_LastRead = DateTime.Now;
byteCount = m_NetworkStream.EndRead(ar);
m_BytesRead += byteCount;
if (!m_HasHeaders || m_RequestType == RequestType.GET)
{
string sBuffer = Encoding.ASCII.GetString(m_Buffer, 0, byteCount);
m_ReadData += sBuffer;
}
AppendBuffer(m_Buffer, byteCount);
m_HasHeaders = UpdateUniqueHeaders();
if (!m_HasHeaders && m_BytesRead > 1024)
{
Program.BlacklistIP(m_RemoteIP, m_ReadData, "No HTTP headers found in the first 1024 bytes");
return;
}
if (byteCount > 0)
{
if (m_RequestType != RequestType.POST && m_RequestType != RequestType.None)
{
m_NetworkStream.BeginRead(m_Buffer, 0, bufferSize, new AsyncCallback(SslRead), m_NetworkStream);
}
else if (m_EndBoundaryIndex == -1) // as long as we haven't found the end of the stream continue reading
{
m_NetworkStream.BeginRead(m_Buffer, 0, bufferSize, new AsyncCallback(SslRead), m_NetworkStream);
return;
}
}
}
catch (Exception e)
{
return;
}
ProcessRequest(m_ReadData);
}
private bool UpdateUniqueHeaders()
{
if (m_RequestType == RequestType.None && m_ReadData.Length > 8)
{
m_RequestType = (m_ReadData.StartsWith("GET ") ? RequestType.GET : m_RequestType);
m_RequestType = (m_ReadData.StartsWith("POST ") ? RequestType.POST : m_RequestType);
m_RequestType = (m_ReadData.StartsWith("OPTIONS ") ? RequestType.OPTIONS : m_RequestType);
}
if (m_RequestType == RequestType.GET || m_RequestType == RequestType.POST)
{
string request = m_ReadData;
if (string.IsNullOrEmpty(m_HttpVersion)) m_HttpVersion = m_ReadData.Substring(request.IndexOf("HTTP", 1), 8);
if (string.IsNullOrEmpty(m_ContentType)) m_ContentType = GetHeader(request, "Content-Type");
if (m_ContentLength == 0)
{
int cLength = 0;
int.TryParse(GetHeader(request, "Content-Length"), out cLength);
m_ContentLength = cLength;
if (m_ContentLength / 1024 / 1024 > 20)
{
IsLargeFileUpload = true; // data is sent directly to a file instead of saving in memory
}
}
}
if (m_RequestType != RequestType.None && !string.IsNullOrEmpty(m_HttpVersion) && (!string.IsNullOrEmpty(m_ContentType) || m_RequestType != RequestType.POST))
{
if (m_RequestType == RequestType.POST)
{
try
{
if (m_IsFileUpload == false)
{
m_IsFileUpload = Segments[1].Replace("/", "") == "upload";
}
}
catch { }
if (m_RequestType == RequestType.POST && m_StartBoundaryBytes == null)
{
m_StartBoundaryBytes = Encoding.ASCII.GetBytes(GetStartBoundary());
m_EndBoundaryBytes = Encoding.ASCII.GetBytes(GetEndBoundary());
}
}
if (string.IsNullOrEmpty(m_Request) && m_Segments.Length <= 1 && m_QueryString == null)
{
// Extract the Requested Type and Requested file/directory
string m_Request = m_ReadData.Substring(0, m_ReadData.IndexOf("HTTP", 1) - 1);
//Replace backslash with Forward Slash, if Any
m_Request = m_Request.Replace("\\", "/");
m_Request = m_Request.Replace("GET ", "");
m_Request = m_Request.Replace("POST ", "");
Uri uri = new Uri("http://localhost" + m_Request);
NameValueCollection query = HttpUtility.ParseQueryString(uri.Query);
//SendHeader(sHttpVersion, "image/jpeg", Program.BlankImageBuffer.Length, " 200 OK");
m_AbsoluteURI = m_Request;
m_Segments = uri.Segments;
m_QueryString = query;
}
if (m_RequestType != RequestType.POST)
{
return true;
}
else if (m_ContentLength > 0 && m_EndBoundaryBytes != null)
{
return true;
}
}
return false;
}
private string GetStartBoundary()
{
return "--" + m_ContentType.Split(';')[1].Split('=')[1];
}
private string GetEndBoundary()
{
return "--" + m_ContentType.Split(';')[1].Split('=')[1] + "--\r\n";
}
private string GetHeader(string request, string key)
{
string result = string.Empty;
int iStartPos = request.IndexOf(key + ":", 0) + key.Length + 1;
if (request.IndexOf(key + ":", 0) > -1)
{
// Get the HTTP text and version e.g. it will return "HTTP/1.1"
int iEndPos = request.IndexOf("\r\n", iStartPos);
result = request.Substring(iStartPos, iEndPos - iStartPos).Trim();
}
return result;
}
private void CleanFile()
{
try
{
if (!string.IsNullOrEmpty(m_TempFilename) && File.Exists(m_TempFilename))
{
using (Stream stream = File.Open(m_TempFilename, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[1024];
stream.Read(buffer, 0, buffer.Length);
//stream.Position = 0;
//stream.Write(data, 0, data.Length);
}
}
}
catch { }
}
private void ProcessRequest(string request)
{
try
{
if (request.Length < 5) return;
List<string> headers = null;
if (request.StartsWith("OPTIONS"))
{
headers = GetCommonHeader("", 0);
headers.Add("Access-Control-Allow-Credentials: true");
headers.Add("Access-Control-Allow-Headers: Authorization, X-Mashape-Authorization, Accept, Content-Type, X-Requested-With, X-PINGOTHER, X-File-Name, Cache-Control");
headers.Add("Access-Control-Allow-Methods: PUT, POST, GET, OPTIONS");
headers.Add("Keep-Alive: timeout=15,max=100");
headers.Add("Access-Control-Allow-Origin: *");
headers.Add("Connection: close");
SendHeader(headers);
return;
}
UpdateUniqueHeaders();
CleanFile();
CloseFile();
if (m_Timer_Check != null) m_Timer_Check.Dispose();
string responseText = Program.ProcessRequest(this);
if (string.IsNullOrEmpty(responseText)) responseText = "\r\n";
byte[] buf = Encoding.ASCII.GetBytes(responseText);
headers = GetCommonHeader("text/html", buf.Length, " 200 OK");
headers.Add("Access-Control-Allow-Origin: *");
SendHeaderAndData(headers, buf);
}
catch (Exception e) { }
finally
{
Dispose();
}
}
private void CloseFile()
{
try
{
if (m_FileStream != null)
{
m_FileStream.Dispose();
m_FileStream = null;
}
}
catch { }
}
/// <summary>
/// This function send the Header Information to the client (Browser)
/// </summary>
/// <param name="sHttpVersion">HTTP Version</param>
/// <param name="sMIMEHeader">Mime Type</param>
/// <param name="iTotBytes">Total Bytes to be sent in the body</param>
/// <param name="mySocket">Socket reference</param>
/// <returns></returns>
public List<string> GetCommonHeader(string mimeHeader = "text/html", int length = -1, string sStatusCode = " 200 OK", string filename = "", bool chunked = false)
{
// if Mime type is not provided set default to text/html
List<string> headers = new List<string>();
headers.Add(m_HttpVersion + sStatusCode);
headers.Add("Server: ExampleTcpWebServer");
if (!string.IsNullOrEmpty(mimeHeader))
{
headers.Add("Content-Type: " + mimeHeader);
}
if (length > -1)
{
headers.Add("Content-Length: " + length);
}
headers.Add("Date: " + DateTime.Now.ToUniversalTime().ToString("ddd, d MMM yyyy HH:mm:ss") + " GMT");
if (!string.IsNullOrEmpty(filename))
{
headers.Add("Content-Disposition: attachment; filename=\"" + filename + "\"");
}
if (chunked)
{
headers.Add("Transfer-Encoding: chunked");
}
return headers;
}
public void SendHeader(List<string> headers)
{
string sHeader = string.Empty;
foreach (string header in headers)
{
sHeader += header + "\r\n";
}
sHeader += "\r\n";
byte[] bSendData = Encoding.ASCII.GetBytes(sHeader);
SendToBrowser(bSendData, bSendData.Length);
}
public void SendHeaderAndData(List<string> headers, byte[] data)
{
string sHeader = string.Empty;
foreach (string header in headers)
{
sHeader += header + "\r\n";
}
sHeader += "\r\n";
byte[] bHeader = Encoding.ASCII.GetBytes(sHeader);
byte[] combined = new byte[bHeader.Length + data.Length];
Array.Copy(bHeader, combined, bHeader.Length);
Array.Copy(data, 0, combined, bHeader.Length, data.Length);
SendToBrowser(combined, combined.Length);
}
/// <summary>
/// Sends data to the browser (client)
/// </summary>
/// <param name="bSendData">Byte Array</param>
/// <param name="mySocket">Socket reference</param>
public void SendToBrowser(byte[] bSendData, int length)
{
try
{
if (Common.TcpHelper.SocketConnected(m_Client.Client))
{
if (m_IsSSL)
{
m_NetworkStream.Write(bSendData, 0, length);
}
else
{
m_Client.Client.Send(bSendData, length, 0);
}
}
else
{
Dispose();
}
}
catch (Exception e)
{
//Console.WriteLine("Error Occurred : {0} ", e);
}
}
#endregion private methods
#region IDisposable
public void Dispose()
{
if (!m_IsDisposed)
{
m_IsDisposed = true;
try
{
if (!string.IsNullOrEmpty(m_TempFilename) && File.Exists(m_TempFilename))
{
File.Delete(m_TempFilename);
}
}
catch { }
CloseFile();
try
{
m_Client.Client.Close(5);
m_Client.Close();
m_Client.Client.Dispose();
}
catch { }
try
{
m_NetworkStream.Dispose();
}
catch { }
try
{
if (Thread.CurrentThread != m_Thread_Read && m_Thread_Read.IsAlive)
{
m_Thread_Read.Join(1000);
if (m_Thread_Read.IsAlive) m_Thread_Read.Abort();
}
}
catch { }
try
{
m_ReadData = null;
m_PostData = null;
m_Buffer = null;
m_TempBuffer = null;
if (m_FullBuffer != null) m_FullBuffer.Dispose();
if (m_Timer_Check != null) m_Timer_Check.Dispose();
m_Timer_Check = null;
}
catch { }
}
}
#endregion IDisposable
}
}

Bluetooth Server C# - 32feet

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

C# 32feet.Net: Handling two bluetooth connections in seperate threads, gives SocketException

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

IRCBot C# connection issues

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

Categories