I've got Android device acting as a client, the PC is a Bluetooth Server, using Bluecove library
Code snippet from the client:
btSocket = serverBt.createRfcommSocketToServiceRecord(myUuid);
btAdapter.cancelDiscovery();
btSocket.connect();
InputStream in = btSocket.getInputStream();
OutputStream out = btSocket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out);
InputStreamReader isr = new InputStreamReader(in);
osw.write(55);
osw.flush();
out.flush();
//osw.close();
logTheEvent("Stuff got written, now waiting for the response.");
int dummy = isr.read();
logTheEvent("Servers response: "+ new Integer(dummy).toString());
And the server:
StreamConnectionNotifier streamConnNotifier = (StreamConnectionNotifier)Connector.open( connectionString, Connector.READ_WRITE );
StreamConnection incomingConnection=streamConnNotifier.acceptAndOpen();
InputStream in = incomingConnection.openInputStream();
OutputStream out = incomingConnection.openOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out);
InputStreamReader isr = new InputStreamReader(in);
int fromClient = isr.read();
System.out.println("Got from client " + new Integer(fromClient).toString());
osw.write(999);
When the osw.close(); at the client is uncommented, the message gets transferred to the server, however, client is then unable to receive the response, IOException with message "socket already closed" is thrown.
However, when osw.close(); is commented, both client and server freeze:
A. Client hangs on reading server's response of course
B. Server hangs on streamConnNotifier.acceptAndOpen();
What should be done to enable two-way communication?
Is my code, or PC Bluetoototh stack, or bluecove to blame?
Bluetooth uses buffered output. That means there is a small memory location that contains all of the data you write to the stream. When this memory location gets full, it writes the buffer data to the socket in a packet. When you prematurely close the socket, that buffer gets wiped, and the data is gone.
In order to force the stream to write, try calling flush()
Something else you could do is set the buffer size to be very small, so data always gets written. The performance won't be very good if you do this, though.
Unfortunately, I don't have all of the code I wrote, but there's a base project here
Related
Working on a project where an Android client communicates with a .Net server via sockets.
It can pass text messages without issue.
It now needs to be expanded to pass an jpeg image.
The server side code:
Dim fs As FileStream = New FileStream(imagePath, FileMode.Open)
Dim br As BinaryReader = New BinaryReader(fs)
sendBytes = br.ReadBytes(fs.Length)
logger.Debug("sending " & sendBytes.Length & " bytes")
clientStream.Write(sendBytes, 0, sendBytes.Length)
clientStream.Flush()
clientStream.Close()
The Android client code:
message send / receive
socket = new Socket(dstAddress, dstPort);
DataOutputStream writer = new DataOutputStream(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
byte[] outputBytes = requestString.getBytes();
writer.write(outputBytes);
Log.d(method, "Message sent: " + requestString);
while ((responseString = reader.readLine()) != null) {
response += responseString + "\n";
}
reader.close();
writer.close();
socket.close();
then trying to reconstruct the image from the response:
byte[] imageBytes = reponse.getBytes();
Log.d(method, "imageBytes.length: " + imageBytes.length);
ByteArrayInputStream is = new ByteArrayInputStream(imageBytes);
ImageView imageV = new ImageView(activity);
imageV.setImageBitmap(BitmapFactory.decodeStream(is));
LogCat error message is: SkImageDecoder::Factory returned null
PLUS the server log says it sent 14548 bytes,
BUT the client log says it received 25294 bytes.
An encoding issue?
I tried adding encoding to the server BinaryReader, no luck.
I also tried on the client side:
imageV.setImageBitmap(BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length));
I have spent hours looking through dozens of posts, I also tried other changes I can't even remember.
but, always "Factory returned null"
What am I doing wrong?
Edit----
Tried changing to
byte[] imageBytes = Base64.decode(response, Base64.DEFAULT)
That generated: IllegalArgumentException: bad base-64
You cannot use readLine() to read the bytes of an image.
Declare a buffer and in a loop read() bytes in the buffer and save them.
You cannot use intermediate Strings either.
If the server only sends an image you could even use
imageV.setImageBitmap(BitmapFactory.decodeStream(socket.getInputStream()));)
variable of position in inputstream may be set to 1024 after the first decode. So add inputstream.reset() before the second decode. Hope that works.
I did a script to exchange data between a client and a server with socket on specific port.
In order, I am expecting:
Server is listening
Client opens a socket
Server akwnoledges by sending a int -> never received !
I just noticed that my client receives the int, when I quit the server brutally
Here is my (simple) code.
Client:
Socket socket = new Socket(SERVER_ADDR, PORT);
DataOutputStream dOut = new DataOutputStream(socket.getOutputStream());
DataInputStream dIn = new DataInputStream(socket.getInputStream());
Log.v("[DEBUG]", "waiting aknowledgement");
status = dIn.readInt(); //<-- BLOCKS HERE
Log.v("[DEBUG]", "ack"); //<-- RECEIVED WHEN SERVER IS EXITED
Server:
try {
DataInputStream stdIn = new DataInputStream(client.getInputStream());
DataOutputStream stdOut = new DataOutputStream(client.getOutputStream());
while (incoming) {
stdOut.writeInt(1);
stdOut.flush();
System.out.println("Waiting...");
var_from_client = stdIn.readInt(); //<-- BLOCKS HERE (BECAUSE CLIENT IS BLOCKED)
// ...
}
} catch (Exception e) {}
How to explain this error?
'Socket not flushing data' has exactly nothing to do with it. This is a deadlock, caused by a bug in your application.
Your server sends an int.
Your client receives the int.
Your server blocks trying to read another int.
Your client doesn't send an int.
The server can never send another int because it is blocked waiting for the non-existent reply int.
Your client blocks while trying to receive another int because the server is blocked from sending it.
Solution: send the int from the client.
Notes:
Flushing the output stream of a socket does nothing, and neither does flushing a DataOutputStream wrapped directly around it.
NEVER ignore exceptions.
I'm receiving an image through a socket in an android aplication, I did debugging and when I'm going to save the image in Drawable d, the program waits for something happens.
I think it has to have relation with clientSocket.getInputStream(); or with the socket.
I have a multithreading server in C++ and when I stop the server, the android aplication continues and I can see the image I sent before. But, I think it's not a server problem, because the socket in the server send the data and shows the message printf("Bytes enviados %d\n", bytesEnviados); which is at the end of the server code.
Here you have the code:
public Drawable mandaMensajeVideo(String mensaje, String ip, int puerto ) throws IOException{
Socket clientSocket = new Socket(ip, puerto);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
outToServer.writeBytes(mensaje);
outToServer.flush();
InputStream inputStream = clientSocket.getInputStream();
Drawable d = Drawable.createFromStream(inputStream, null);
clientSocket.close();
outToServer.close();
return d;
}
Thanks!
Sounds like the end of the inputStream is never reached, as you never properly close the communication.
I am writting simple program to connect server by socket in android.
But when i try to read data from socket's outputstream it will send automatically RST request. so my connection gets closed. but i want my connection to open always.
Please any one help me.
Thank you.
try {
Socket socket = new Socket("xxx.xxx.x.xx", 9083);
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println("Testing");
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(
inputStream));
String readObject = reader.readLine();
System.out.println(readObject);
} catch (Exception e) {
e.printStackTrace();
}
The most usual reason for 'connection reset' is that you have written to a connection that has already been closed by the other end. In other words, an application protocol error.
public void sendToServer(String fileToSend, String ip, int sendPort)
{
int port = sendPort;
String url = ip;
File file = new File(fileToSend);
String fileName = file.getName();
Socket sock;
try {
sock = new Socket(url,port);
//Send the file name
OutputStream socketStream = sock.getOutputStream();
ObjectOutput objectOutput = new ObjectOutputStream(socketStream);
objectOutput.writeObject(fileName);
//Send File
byte [] mybytearray = new byte [(int)file.length()];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
os.write(mybytearray,0,mybytearray.length);
fileSentOkay();
os.flush();
sock.close();
} catch (UnknownHostException e) {
hostNotFound();
} catch (IOException e) {
hostNotFound();
}
}
When I try to send something to the server when the server isn't listening for the connection, the phone keeps attempting to send the file. As a result of this, my Android program will eventually force close.
How could I set a time out for this to happen? Would I have to use something like setSoTimeout() on the socket that is sending the data?
First: Just in case: Don't do network stuff on the UI Thread. Bad Things will happen (tm)
Second: setSoTimeout() should give you a timeout in case the server accepts the connection, but does not reply (or in case there is no reply from the network at all). In case the connection is rejected the socket should fail significantly faster.
Edit: In case the constructor of the Socket class is already taking that long, try using the connect(SocketAddress, int) method. Use InetSocketAddress as parameter:
Socket s = new Socket();
s.connect(..., 1000);