Reading from Bluetooth socket - java

I have a problem with reading from Bluetooth socket. I create the socket:
private OutputStream outputStream;
private InputStream inStream;
socket=device.createRfcommSocketToServiceRecord(uuids[0].getUuid());
socket.connect();
outputStream = socket.getOutputStream();
inStream = socket.getInputStream();
After connection is established I send some instructions to the Bluetooth device after which I need to get an answer back(answer is always the same 5 bytes). But from time to time when I do this:
byte[] packetBytes = new byte[5];
inStream.read(packetBytes);
the app freezes.
I tried inputstream.available and used it with previous devices, but it would always return 0 here.
And I tried waiting before reading but still nothing. When I try those same commands on PC I get an answer.

For anybody that is having the same problem as me. For now the solution that I am using is a new Thread that constantly reads from an input socket with inStream.read(packetBytes);
When something is read we just send it to our main Thread to be processed.

Related

Good behavior of Java Server built using sockets

I have this piece of server code:
Socket serverSocket = new ServerSocket(8080);
socket = serverSocket.accept();socket = serverSocket.accept();
byte buf[] = new byte[2];
StringBuilder builder = new StringBuilder();
InputStream is = socket.getInputStream();
int r;
while ((r = is.read(buf)) > 0) {
builder.append(new String(buf, 0, r));
}
socket.getOutputStream().write(....
My client only connects to the server, sends bytes through the outputstream and expects some kind of answer from the server.
Socket socket = new Socket("localhost", 8080);
socket.getOutputStream().write("some string".getBytes());
// then manipulating with input stream
The problem is the fact that integer r is never -1, because it becomes -1 only when connection is closed (as I understood). Because of that, my server hangs on "is.read(buf)" expecting client to send something else, while client has finished sending data and already expecting server to send the response.
My question: how does a server know that a client has finished sending its data? What is the appropriate byte buffer size? If I expect large data to be transfered through network, how do I know how many times "is.read(buf)" has to be called? What is the correct server behavior in this case?
UPD: I need them to communicate through the sockets like in chat application. So I cannot close Outputstream of the client socket. Though I tried to close outputstream after writing into it, that led to java.net.SocketException saying that socket is closed.

mMediaRecorder.setOutputFile(ParcelFileDescriptor.fromSocket(mSocket)) - nothing written to mSocket

I have Service which records video from back camera:
this.mMediaRecorder = new MediaRecorder();
this.mMediaRecorder.setCamera(mCamera);
this.mMediaRecorder.setVideoSource(VideoSource.CAMERA);
this.mMediaRecorder.setOutputFormat(OutputFormat.DEFAULT);
this.mMediaRecorder.setVideoEncoder(VideoEncoder.DEFAULT);
this.mMediaRecorder.setVideoSize(photo_resolution[0], photo_resolution[1]);
this.mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(this.mSocket);
this.mMediaRecorder.setOutputFile(this.mParcelFileDescriptor.getFileDescriptor());
this.mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
this.mMediaRecorder.prepare();
this.mMediaRecorder.start();
Video doesn't have a sound. I connecting to the server with following code:
this.mSocket = new Socket();
this.mSocket.connect(new InetSocketAddress(...), 30000);
this.in = new BufferedReader(new InputStreamReader(this.mSocket.getInputStream(), "UTF-8"));
this.out = this.mSocket.getOutputStream();
this.out.write(("some string" + "\n").getBytes("UTF-8"));
this.out.flush();
...
Every needed permissions I have already added to AndroidManifest.xml.
The problem is that video isn't broadcasted to server. I tried to replace this.mParcelFileDescriptor.getFileDescriptor() to "/sdcard/video.mp4", everything was alright - video recorded correclty. But it doesn't sends to socket. Nothing happened clientside (in my app), but serverside thrown me exception java.net.SocketTimeoutException: read timed out. I tried this code serverside:
byte[] bytes = new byte[1024];
int read = mSocket_inputStream.read(bytes, 0, 1024);
System.out.println(read);
which debug me count of read bytes from client (from my app) - nothing was debugged in console, because 0 bytes was sent. Help me solve this problem please. I didn't found solution in google.
File descriptor only works for local server socket in MediaRecorder.
this.mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(this.mSocket);
this.mMediaRecorder.setOutputFile(this.mParcelFileDescriptor.getFileDescriptor();
You can create your own LocalServerSocket and then pass data to actual server socket from your local server socket
To know more about local server socket you can go through https://developer.android.com/reference/android/net/LocalServerSocket.html
The more efficient way will be to use MediaCodec API for recording as it will provide you data frame by frame in format of byte buffer and you can send that data on to server.

does close a socket will also close/flush the input/output stream

I have a program like that,
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
...some read and write here...
socket.close;
The code works fine. But I am not sure whether the in/out was close if I close the socket or not. Also I didn't call out.flush(), how the data going to be sent out?
Closing the socket doesn't flush the output stream but closes both streams and the socket.
Closing the input stream doesn't flush the output stream but closes both streams and the socket.
Closing the output stream flushes it and closes both streams and the socket.
You should close the outermost OutputStream you have wrapped around the one you got from the socket. For example:
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dos = new DataOutputStream(bos);
Close 'dos'. That flushes it, flushes 'bos', and closes everything.
Flush on close is documented in the Javadoc for FilterOutputStream.
Another answer: In Java, when I call OutputStream.close() do I always need to call OutputStream.flush() before?
says that yes! It will be flushed if you close it manually

Java passing BufferedReader, DataOutputStream and Sockets to a runnable thread class leads to socket exception upon writing to stream

I have two 'Client's, one 'Server' and potentially a 'ThreadManager' that implements runnable.
The two Clients connect with Server via TCP and partake in a protocol handshake/ authentication thing (successful), then I attempted to pass the existing BufferedReaders, DataOutputStreams and Sockets to 'ThreadManager' to manage threading messages between Client1 and Client2:
SERVER:
ThreadManager tManager = new ThreadManager(serviceToClient1, inputStream, outputStream, serviceToClient2, inputStream2, outputStream2);
new Thread(tManager).start();
serviceToClient1.close();
serviceToClient2.close();
THREADMANAGER:
public ThreadManager(Socket cli1, BufferedReader inputStream, DataOutputStream outputStream, Socket cli2, BufferedReader inputStream2, DataOutputStream outputStream2)
{
this.cli1 = cli1;
this.inputStream = inputStream;
this.outputStream = outputStream;
this.cli2 = cli2;
this.inputStream2 = inputStream2;
this.outputStream2 = outputStream2;
}
this constructs successfully, however on .start() called from Server, debugging shows a "Socket Exception: Socket Closed" error as soon the following is called from within ThreadManager:
outputStream.writeBytes("NUMBER: " + i + "\n");
I'm not sure where the problem is created, would I need to close connections and recreate Sockets and streamreaders/writers from within ThreadManager? I tried only passing the Sockets in the ThreadManager constructor and then creating new BufferedReader... etc. but this seems to be just as bad. Could anyone suggest either the solution, or where the problem lies (or both!) :) thanks.
You close your Socket before you try to read from it on your Thread, so you get an exception.

Socket stream hangs when using IOUtils.copy()

I want to send an InputStream containing XML from the client to a server. Said server manipulates the XML stream using Streaming API for XML (StAX) and sends it back to the client.
I mange to send the XML to the server, the client receives the answer, but doesn't exit because the server never finishes reading the InputStream form the client.
But when the server is just dumping the input to System.out instead of sending something, reading finishes...
edit I forgot to mention that IOUtils.copy() is running in two separate threads on the client.
Here some code to reproduce this, I've replaced the StAX part with IOUtils.copy() on the server.
Server
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);
Client
Socket socket = new Socket(host, port);
FileInputStream fin = new FileInputStream(file);
OutputStream out = socket.getOutputStream();
IOUtils.copy(fin, out)
InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)
You must flush and close InputStream and OutputStream.
like this:
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);
//add
out.flush();
in.close();
out.close;
You are probably creating a deadlock.
Client - sends data to the server.
Server - loops data back to the client.
Client - reads data (that the server looped back)
So, while the client is sending data to the server, the server is sending it back to the client.
The client isn't reading that data, it's busy sending.
At some point the TCP buffers fill up, and the server blocks on sending more data to the client. This means the server is blocked on sending data, so eventually the TCP buffers on the receiving side of the server fills up as well, and the client blocks on sending data. Since the client is now blocked on sending, it'll never get to the part where it reads the data that is looped back, so the server will never un-block.
If you're sending a small document, you might not experience this, as all the data fits in the buffers, but once you fill up the buffers, the system will deadlock.
You have to multiplex the sending/receiving. e.g. you could start up a thread on the client that does
InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)
That way receiving can be done in parallel with the client sending data
Or you could use 2 threads on the server side. One for receiving the data, posting data to be sent back to another thread doing the sending (you'll have to build up an internal queue in this case between the threads).
As far as I remember IOUtils.copy() does not flush and does not close the stream. It seems that you do not call neither flush nor close too. Try it. I believe that this is your problem.

Categories

Resources