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.
Related
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.
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.
using DataInputStream to get an int and long sent from the Android client to this Java desktop server. After that a pdf file is received from the Android client. for a total of 3 files sent by the client to the Server. the problem is when sending in the other direction.
i have to close both the input and output streams right after the while loop. if i don't do that, the pdf file will be corrupted and the program will stop and get stuck on the while loop and not continue execution to the end of the thread.
if i have to close the input and output steams, the socket is getting closed. how do i reopen the same socket?
i need to reopen the same socket because of the need to send a message back to the Android client that the server received the pdf file from to send it a confirmation that the file was safely received by the server.
there are multiple Android clients connected to the same single Java server, so i imagine that the same socket is needed to send a message back to the client. without the socket it would be difficult to determine which client to send the message to.
byte[] buffer = new byte[fileSizeFromClient];
while((count = dis.read(buffer)) > 0){
bos.write(buffer, 0, count);
}
dis.close(); // closes DataInputStream dis
bos.close(); // closes BufferedOutputStream bos
EDIT:
code from the client
dos.writeInt((int)length); // sends the length as number bytes is file size to the server
dos.writeLong(serial); // sends the serial number to the server
int count = 0; // number of bytes
while ((count = bis.read(bytes)) > 0) {
dos.write(bytes, 0, count);
}
dos.close(); // need to close outputstream or result is incomplete file sent to server
// and the server hangs, stuck on the while loop
// if dos is closed then the server sends error free file
No. You can't reopen a socket. You have to make a new one. You don't have to close your socket once you're done with your file transfer. The server can still reuse it send your message reply. Since you've already sent the file size, your server can use that to know when your client is done sending the complete file. After that, your server can send your reply to the client.
Try this for your current loop.
int bytesRead = 0;
while((count = dis.read(buffer)) > 0 && bytesRead != fileSizeFromClient){
bytesRead += count;
bos.write(buffer, 0, count);
}
bos.close();
//don't close the input stream
I am fist connecting through vpn client then I am able to do telnet and also able to get response when i paste request string on terminal.
Same request if I am trying through java program, I am not getting any response.
I can see using netstat there is established TCP connection when i try through java.
TCP 10.2.2.22:1154 184.23.23.61:7565 ESTABLISHED
Here is the java client code which sends the request.
Socket client = new Socket(serverIp, port);
OutputStream out = client.getOutputStream();
InputStream in = client.getInputStream();
String test = "TUE231363**";
StringBuffer response = new StringBuffer("response : ");
out.write(test.getBytes());
out.flush();
int c;
System.out.println("waiting for response.......>>>>>>>>>>>>>");
while ((c = in.read()) != -1) {
if (isEndOfResponse(c))
break;
System.out.print((char) c);
response.append(c);
}
client.close();
System.out.println(response.toString());
every time after few minutes [5-6 min] it exits without any response.
I am bit new to networking, can anyone suggest what I am missing.
I assume that you are telnetting to the same IP address and port that you are trying to connect to from Java.
The fact that telnet connects, and your client also appears to connect would imply that the server is running, and that it has created an bound a ServerSocket on the right IP / host. It is probably even calling accept properly. But is seems like the server is either not reading the request at all, or it is failing to send a response.
Either way, the problem is most likely on the server side ... and there's not much we can say without seeing the server-side code.
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.