Creating and destroying bluetooth sockets - c#

I am currently trying to write an app for android with Xamarin where I want to create and destroy sockets to the same device, and then redo that process over again. I have written both client and server code. I am having a problem doing that, since the app always crashes on the server side when it tries to read data from the client for a second time.
What I mean is that it is always successful the first time around, but the second time around, it always crashes. We figured out that the problem was on the client though cause once we started keeping the sockets open and reusing them instead of closing them and recreating a new one when needed, it worked as intended and did not crash. Here is the code we ended up using:
[SERVER]
public class BluetoothSocketListener {
private BluetoothScanner _scanner;
private BluetoothServerSocket serverSocket;
private string TAG = "Socket Listener: ";
private Thread listenThread;
public BluetoothSocketListener(BluetoothScanner scanner, UUID uuid) {
_scanner = scanner;
BluetoothServerSocket tmp = null;
try {
tmp = scanner.Adapter.ListenUsingInsecureRfcommWithServiceRecord("AGHApp", uuid);
} catch(Exception e) {
Console.WriteLine(TAG + "Listen failed, exception: " + e);
}
serverSocket = tmp;
listenThread = new Thread(new ThreadStart(StartListening));
listenThread.Start();
}
private void StartListening() {
Console.WriteLine(TAG + "Listening...");
BluetoothSocket socket = null;
while(_scanner.Running){
try {
socket = serverSocket.Accept();
}catch(Exception e) {
Console.WriteLine(TAG + "Accept failed: " + e);
break;
}
if (socket != null) {
lock (this) {
ReadData(socket.InputStream);
socket.Close();
}
}
}
serverSocket.Close();
}
private void ReadData(Stream stream) {
// Check to see if this NetworkStream is readable.
if(stream.CanRead){
byte[] streamData = new byte[1024];
StringBuilder completeMsg = new StringBuilder();
int bytesRead = 0;
// Incoming message may be larger or smaller than the buffer size.
do{
bytesRead = stream.Read(streamData, 0, 1);
completeMsg.AppendFormat("{0}", Encoding.ASCII.GetString(streamData, 0, bytesRead));
}
while(stream.IsDataAvailable());
// Print out the received message to the console.
Console.WriteLine("Message : " + completeMsg);
}
else{
Console.WriteLine("Cannot read from stream");
}
}
}
[CLIENT]
private void SendData(BluetoothDevice device, string msg){
Console.WriteLine(TAG + "Finding socket");
BluetoothSocket socket = null;
if(sockets.ContainsKey(device.Address)) {
socket = sockets[device.Address];
}
else {
socket = device.CreateInsecureRfcommSocketToServiceRecord(_uuid);
socket.Connect();
sockets.Add(socket);
}
Console.WriteLine(TAG + "Socket connected, writing to socket");
byte[] bMsg = Encoding.ASCII.GetBytes(msg);
socket.OutputStream.Write(bMsg, 0, bMsg.Length);
socket.OutputStream.Close();
}
As can be seen, I never actually close the sockets on the client side after I send the message. This is not the problem though since if this is necessary, I can easily do this in some other function.
What I would like is to create and close the socket every time I want to send a message, since I only want to send something every 15 minutes, and the device might have moved and is no longer available. It is also not necessary to keep track of the devices. Fire and forget. This is what we started with and would like to have something similar to this as well:
private void SendData(BluetoothDevice device, string msg){
BluetoothSocket socket = device.CreateInsecureRfcommSocketToServiceRecord(_uuid);
socket.Connect();
Console.WriteLine(TAG + "Socket connected, writing to socket");
byte[] bMsg = Encoding.ASCII.GetBytes(msg);
socket.OutputStream.Write(bMsg, 0, bMsg.Length);
socket.OutputStream.Close();
socket.Close();
Console.WriteLine(TAG + "Socket closed");
}
Something to notice is that the server actually closes the socket after it receives the message, why is that even working? And why can't I close the socket on the client side? Am I missing something integral here?
The exception is a Java.IO exception, where the message reads: bt socket closed, read -1
Would really appreciate some help!

Related

TcpListener won't acknowledge connections

So I am writing a simple client-server application. It should send a packet, then wait to receive a packet, than send one etc... The problem is, it recieves the first packet, but when I start the TcpListener in the second iteration, it gives me this error:
No connection could be made because the target machine actively
refused it 127.0.0.1:13
private void listenForConnections()
{
bool prejelPaket = false;
listener = new TcpListener(IPAddress, port);
listener.Start();
while (!packetReceived)
{
try
{
client = listener.AcceptTcpClient();
listener.Stop();
networkStream = client.GetStream();
byte[] message = new byte[1024];
networkStream.Read(message, 0, message.Length);
networkStream.Close();
string strMessage = Encoding.UTF8.GetString(message);
packetReceived= true;
MessageBox.Show("received message: " + strMessage);
client.Close();
}
catch (Exception ee)
{
thListen.Join();
}
}
}
private void sendPacket(object pClient)
{
string message = "test message;
try
{
client = (TcpClient)pClient;
client.Connect(IPAddress, port);
networkStream = client.GetStream();
byte[] strMessage = Encoding.UTF8.GetBytes(message);
networkStream.Write(strMessage, 0, strMessage.Length);
networkStream.Close();
client.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Create the client / networkstream once. Store them in a property until you are finished sending and receiving. Then close and dispose. Do not stop / close the connection between each iteration.
Move the
listener.Stop();
outside the while loop.
EDIT: to explain why
The reason why it works the first time but second iteration fails is because after the first client is accepted from client = listener.AcceptTcpClient() the next line of code calls listener.Stop() which stops listening for connections. Any subsequent calls to listener.AcceptTcpClient() will throw an InvalidOperationException. Moving listener.Stop() outside the while loop only stops listening for connections once it exits the loop.
Looking at it again packetReceived is set to true in the first iteration as well, so it's going to exit the while loop after the first client anyway, is this the intended behaviour?

Incomplete messages (C# TCP/IP Client)

First of all, I'm absolutely not a network programmer. What I try to do, is a very simple TCP/IP communication between a Java server and a C# client.
Java server:
public void run(){
try {
// Open server socket
_server = new ServerSocket(SERVER_PORT);
_client = _server.accept();
System.out.println("ComInterface: client connected.");
// Wait for a client data output stream
while(true){
// Receive message from client
BufferedReader is =
new BufferedReader(new InputStreamReader(_client.getInputStream()));
msg = is.readLine();
// Process message
if(msg!=null){
System.out.println("ComInterface: Message Received : <" + msg + ">.");
processMessage(msg); // Independant method
}
else{
System.out.println("ComInterface: client closed connection.");
_client.close();
_client = _server.accept();
System.out.println("ComInterface: client connected.");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String msg){
try {
// Out stream
DataOutputStream os = new DataOutputStream(_client.getOutputStream());
os.writeBytes((String)(msg+"\n"+(char)13));
os.flush();
System.out.println("ComInterface: Message <" + msg + "> sent");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
And here's the C# client:
public class ComInterface : MonoBehaviour
{
public const String SERVER_IP = "127.0.0.1"; // Localhost
public const int PORT = 1100; // Default port
public const int READ_BUFFER_SIZE = 5000; // 4.8828125 kilobytes
private TcpClient _client;
private ASCIIEncoding _asen;
private byte[] _readBuffer;
private String _msg;
public Boolean connected { get; internal set; } // setter is for internal use only
/**
* Initialize internal variables (buffer, socket...)
*/
public ComInterface()
{
connected = false;
_client = new TcpClient();
_asen = new ASCIIEncoding();
_readBuffer = new Byte[READ_BUFFER_SIZE];
_msg = String.Empty;
}
/**
* Connect to server at SERVER_IP:PORT
* Return true if connection was a success, or false if failure.
*/
public Boolean Connect()
{
try
{
_client.Connect(SERVER_IP, PORT);
connected = true;
Array.Clear(_readBuffer, 0, _readBuffer.Length);
Debug.Log("TCPClient: <Connect> Connected to the server");
// Start an asynchronous read invoking ReceiveComMessage
_client.GetStream().BeginRead(_readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(ReceiveComMessage), _client.GetStream());
}
catch (Exception ex)
{
Debug.Log("TCPClient: <Connect> Cannot connect to the server - " + ex.Message);
connected = false;
}
// Return connection state
return connected;
}
/**
* Received a message from Communicator
*/
private void ReceiveComMessage(IAsyncResult ar)
{
int BytesRead;
String msg;
try
{
BytesRead = _client.GetStream().EndRead(ar);
if (BytesRead < 1)
{
// if no bytes were read server has close.
Debug.Log("TCPClient: <ReceiveComMessage> The server has closed (BytesRead<1)");
this.Disconnect();
return;
}
// Convert the byte array the message was saved into,
msg = Encoding.ASCII.GetString(_readBuffer);
Debug.Log("C# Message: \"" + msg + "\""); // Output example in log below
BytesRead = 0;
Array.Clear(_readBuffer, 0, _readBuffer.Length);
// Start a new asynchronous read into readBuffer.
_client.GetStream().BeginRead(_readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(ReceiveComMessage), _readBuffer);
}
catch (Exception ex)
{
Debug.Log("TCPClient: <ReceiveComMessage> The server has closed (Exception):" + ex.Message + " see " + ex.StackTrace);
this.Disconnect();
}
The main problem is that all the message are arriving incomplete. Here's the log trace:
C#: Message "{
C#: Message ""sender":"Bob"",
C#: Message ""recipient":",
etc...
Instead of for instance
C#: Message "{"sender":"Bob","recipient":[1,2,3]}"
I'm a bit confused and I'd need some help to resolve this. Thank you very much!
TCP is a stream-oriented connection, not message-oriented. It has no concept of a message. When you write out your serialized string, it only sees a meaningless sequence of bytes. TCP is free to break up that stream up into multiple fragments and they will be received at the client in those fragment-sized chunks. It is up to you to reconstruct the entire message on the other end.
In your scenario, one would typically send a message length prefix. This way, the client first reads the length prefix so it can then know how large the incoming message is supposed to be.
I would seriously consider using something like Google's Protocol Buffers as a good way of declaring your messages and then streaming them with the size prefix option. The nice thing is that you define your set of messages once and then use the available tools to automatically generate C++, Java, C#, etc code from the message definitions. This will help in having a consistent messaging set that works between languages.
A message (any data, I mean), when sent through a socket, is divided into several packets.
When printing each received packet, you don't see your whole message.
You should define an end of message string (something like ".#."). Until you receive this sequence, you keep concatenating the messages you receive.
This is what session protocols (that is, protocols that run on the top of TCP) do.
Hope this helps.
Regards, Calil
Take a look at this example...
Java TCP Server...
import java.net.*;
import java.io.*;
public class TcpServer
{
public static void main(String h[])
{
try
{
ServerSocket serverSocket = new ServerSocket(1100);
Socket socket = serverSocket.accept();
System.out.println("Client Accepted");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Received: " + bufferedReader.readLine());
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
printWriter.println("Hello Theo. Welcome to socket programming.");
} catch (Exception e)
{
System.out.println(e);
}
}
}
C# TCP Client...
using System;
using System.IO;
using System.Net.Sockets;
class Program
{
static void Main(string[] args)
{
try
{
var client = new TcpClient("localhost", 1100);
var stream = client.GetStream();
var streamWriter = new StreamWriter(stream);
streamWriter.WriteLine("My name is Theo");
streamWriter.Flush();
var streamReader = new StreamReader(stream);
Console.WriteLine("Received: " + streamReader.ReadLine());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("Press a key to continue.");
Console.ReadKey();
}
}

Getting Error thrown when TCP connect lost

I have a block of code that "listens" on a TCP port and just sends an string back no matter what is sent. The issue is the client side is just testing to see if the port is active then disconnecting. At which point I get an error thrown.
Cannot access a disposed object
Object name: 'System.Net.Socket.NetworkSystem'
I think the issue is that this code is on a thread and when the connection closes the while loop references a disposed object... how should I prevent the error from firing when the client closes the connection?
//Cretae listener to accept client connections
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] rcvBuffer = new byte[BUFSIZE]; // Receive buffer
int bytesRcvd; // Received byte count
while (ServiceRunning) // Run forever, accepting and servicing connections
{
try
{
// Receive until client closes connection, indicated by 0 return value
int totalBytesEchoed = 0;
//I THINK THIS IS WHERE THE PROBLEM IS .. THE CLIENTSTREAM.READ???
while (((bytesRcvd = clientStream.Read(rcvBuffer, 0, rcvBuffer.Length)) > 0) && (ServiceRunning))
{
clientStream.Write(responseBytes, 0, responseBytes.Length);
WriteEventToWindowsLog("GSSResponderService", "Received "+System.Text.Encoding.UTF8.GetString(rcvBuffer), System.Diagnostics.EventLogEntryType.Information);
totalBytesEchoed += bytesRcvd;
}
WriteEventToWindowsLog("GSSResponderService", "Responded to " + totalBytesEchoed.ToString() + " bytes.", System.Diagnostics.EventLogEntryType.Information);
// Close the stream and socket. We are done with this client!
clientStream.Close();
tcpClient.Close();
}
catch (Exception e)
{
//THIS IS GETTING TRIGGERED WHEN A CONNECTION IS LOST
WriteEventToWindowsLog("GSSResponderService", "Error:" + e.Message, System.Diagnostics.EventLogEntryType.Error);
clientStream.Close();
tcpClient.Close();
break;
}
}
}
According to MSDN, Read method of NetworkStream class throws IOException when the underlying Socket is closed and ObjectDisposedException when the NetworkStream is closed or there is a failure reading from the network. The same exceptions are thrown by Write method.
Therefore it shoud be enough to catch these 2 exception types and take appropriate action in exception handlers.
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] rcvBuffer = new byte[BUFSIZE]; // Receive buffer
int bytesRcvd; // Received byte count
while (ServiceRunning) // Run forever, accepting and servicing connections
{
try
{
// Receive until client closes connection, indicated by 0 return value
int totalBytesEchoed = 0;
try
{
while (((bytesRcvd = clientStream.Read(rcvBuffer, 0, rcvBuffer.Length)) > 0) && (ServiceRunning))
{
clientStream.Write(responseBytes, 0, responseBytes.Length);
WriteEventToWindowsLog("GSSResponderService", "Received "+System.Text.Encoding.UTF8.GetString(rcvBuffer), System.Diagnostics.EventLogEntryType.Information);
totalBytesEchoed += bytesRcvd;
}
}
catch(IOException)
{
//HERE GOES CODE TO HANDLE CLIENT DISCONNECTION
}
catch(ObjectDisposedException)
{
//HERE GOES CODE TO HANDLE CLIENT DISCONNECTION
}
WriteEventToWindowsLog("GSSResponderService", "Responded to " + totalBytesEchoed.ToString() + " bytes.", System.Diagnostics.EventLogEntryType.Information);
// Close the stream and socket. We are done with this client!
clientStream.Close();
tcpClient.Close();
}
catch (Exception e)
{
WriteEventToWindowsLog("GSSResponderService", "Error:" + e.Message, System.Diagnostics.EventLogEntryType.Error);
clientStream.Close();
tcpClient.Close();
break;
}
}
}

Android socket client works on Java server but not C# server

I'm new to Android programming and I'm trying to send some text data to PC via TCP.
I built an example I found on the web, which has an Android Client and a Java Server.
The server runs ok.
When I run the Android Client on the emulator or on the phone, both works perfectly well.
The problem is that I need it to communicate to a C# application, so I built an TCP server in C#.
Now, if I run the Client on the emulator it works and the C# server receive the data (a little messed, but it's probably an text encoding problem which I think won't be hard to solve). But anyway, the data is arriving at the c# server.
If I try to run the same Client on the phone I can't even connect to the C# server. I get a timeout error when connecting.
Also I can ping the PC from phone and ping the phone from PC, so I don't think it's a network problem.
I have some experience in C# but not much on sockets and even less on Android. So I ask, is there any difference on TCP protocols used by Java and C#? Sorry if it's a dumb question, but I googled it for hours and haven't found a clue.
Any ideas of what may be causing it?
The Java server code is this:
public class Servidor {
private static boolean executando = true;
private static String mensagem;
private static final int PORTA = 1234;
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(1234);
InetAddress addr = InetAddress.getLocalHost();
System.out.println("----------- SERVER CONNECTED "
+ addr.getHostAddress() + " PORT " + PORTA
+ " -----------");
System.out.println("Waiting connections.");
Socket socket = server.accept();
System.out.println("Server -> Connected Ip "
+ socket.getInetAddress().getHostAddress());
DataInputStream in = new DataInputStream(socket.getInputStream());
try {
while (executando) {
mensagem = in.readUTF();
System.out.println("Server-> Received Message: "
+ mensagem);
}
System.out.println("Servidor-> Finalizado.");
in.close();
socket.close();
server.close();
} catch (Exception e) {
System.err.println("Server -> Error: " + e.getMessage());
executando = false;
}
} catch (Exception e) {
e.printStackTrace();
}
} }
The C# Server code is this:
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Server()
{
Console.WriteLine("\nStarting server...");
this.tcpListener = new TcpListener(IPAddress.Any, 1234);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
Console.WriteLine("\nWaiting for clients to connect...");
this.tcpListener.Start();
while (true)
{
blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
create a thread to handle communication
with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
Console.WriteLine("\nIncoming from client...");
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
a socket error has occured
break;
}
if (bytesRead == 0)
{
the client has disconnected from the server
break;
}
message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
Console.WriteLine("\nReceived: \n\n" + encoder.GetString(message, 0, bytesRead));
}
tcpClient.Close();
}
}
If needed, the Android Client code is exactly the one on the following link:
http://www.portalandroid.org/comunidade/viewtopic.php?f=7&t=11077&p=127577

Error in asynchronous read from the NetworkStream

I have make an application to communicate with an IP Camera. That is configured to make connection on a predefined address. And TCP Listener is running on that address and accepts connection from camera. When camera connects i send command to get MJpeg stream from camera and camera starts sending stream in response to command.
I am using asynchronous method to read stream from socket. But after sometime my application is stuck while reading data from network stream.
I am using this code to read Data from network stream and i have write some messages on the screen to get status of camera connection.
private void ReadData()
{
try
{
string msg = "Reading Data... client connected " + _camClient.Connected.ToString() +
"... netStream Readable " +
_netStream.CanRead.ToString();
Console.WriteLine(msg);
_callback = new AsyncCallback(GetData);
_buffer = new byte[Buffersize];
_async = _netStream.BeginRead(_buffer, 0, Buffersize, _callback, null);
}
catch (Exception ex) { Console.WriteLine("ReadData: " + ex.Message); }
}
private void GetData(IAsyncResult result)
{
try
{
int read = _netStream.EndRead(result);
if (read > 0)
{
_data = new byte[read];
Array.Copy(_buffer, 0, _data, 0, read);
ProcessData();
}
ReadData();
}
catch (Exception ex) { Console.WriteLine("GetData: " + ex.Message); }
}
Firstly asynchronous methods on network streams are well known for loosing data or for never returning data!
In your case it could be the ProcessData call is blocking.
What you should do is to spawn a new background thread with a blocking listener (non asynchronous) and then use a new thread to read the data while the listener continues to listen.
I have an example here.
private static Socket s_chatListener;
public static void Listen(IPAddress LocalIPAddress, int Port)
{
IPEndPoint ipend = new IPEndPoint(LocalIPAddress, Port);
s_chatListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s_chatListener.Bind(ipend);
s_chatListener.Listen(10);
while (true)
{
Socket handler = s_chatListener.Accept();
ParameterizedThreadStart pst = new ParameterizedThreadStart(loadMessageFromSocket);
Thread t = new Thread(pst);
t.Start(handler);
}
}
private static void loadMessageFromSocket(object socket)
{
Socket handler = (Socket)socket;
string data = "";
while (true)
{
byte[] butes = new byte[1024];
int rec = handler.Receive(butes);
data += ASCIIEncoding.ASCII.GetString(butes);
if (data.IndexOf("\0") > -1)
break;
}
handler.Shutdown(SocketShutdown.Both);
handler.Close();
Console.Write(data);
}
Now just call the Listen Method from a new Thread in your main form or caller class.
Hope this helps.

Categories

Resources