Socket connectivity loss when sending live streaming data - java

I'm struggling here...
I'm trying to determine if data was successfully sent to the server through a TCP socket using the OutputStream object. For testing on emulator socket communications is loss after 30 sec. For write data OutputStream.write(); its doesn't throw an exception , and local server continuously running its not crashing, only tcp socket connection is loss after some time. All the methods in the socket class return as though the socket is active and working. Is there anything I'm doing wrong here? Is there any socket implementation or stream implementation I can use to get an exception or error when the stream/ socket doesn't actually send the data in the buffer? Also setting setSoTimeout() on the socket doesn't seem to do anything.
Please guide me...
Here is my code:
private void sendRec() {
int lstream;
int port = 1012;
byte[] byterecv = new byte[1040];
while (true) {
System.out.println("POOL-2");
synchronized (recSendThread) {
try {
recSendThread.wait(20);
} catch (InterruptedException e) {
}
}
if (stopcall == true) {
// break;
}
try {
// Provides a client-side TCP socket
Socket clientRec = new Socket();
// serverSocket = new ServerSocket(port);
// serverSocket.setSoTimeout(5000);
// Connects this socket to the given remote host address and
// port
clientRec.connect(new InetSocketAddress("192.168.1.36", port));
System.out.println("Just connected to "
+ clientRec.getRemoteSocketAddress());
System.out.println("SENTS Rec BEFORE");
// output streams that write data to the network
OutputStream outToServerRec = clientRec.getOutputStream();
DataOutputStream outStreamRec = new DataOutputStream(
outToServerRec);
outStreamRec.write(bData);
System.out.println("SENTS Rec AFTER");
// input streams that read data from network
InputStream inFromServerRec = clientRec.getInputStream();
// clientRec.setSoTimeout(5000);
DataInputStream inStreamRec = new DataInputStream(
inFromServerRec);
while ((lstream = inStreamRec.read(byterecv)) != -1) {
System.out.println("startrec bytearray -- "
+ byterecv.length);
bos1.write(byterecv, 0, lstream);
}
inStreamRec.close();// for closing dataouputstream
clientRec.close();// for closing socket connection
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is my receiver and player code..
/**
* start receiving the voice data from server
* */
protected void startplay() {
System.arraycopy(frndid, 0, playByteData, 0, 4);
System.arraycopy(userid, 0, playByteData, 4, 4);
ByteBuffer.wrap(sessionid).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().
put(call_sessionid);
System.arraycopy(sessionid, 0, playByteData, 8, 4);
int lstream;
int port = 1014;
while (true) {
System.out.println("POOL-3");
try {
if (stopcall == true) {
System.out.println("BREAKEDDDD1111");
//break;
}
// Host name
// port++;
InetAddress addressPlay = InetAddress.getByName("192.168.1.36");
// Creates a new streaming socket connected to the target host
Socket clientPlay = new Socket(addressPlay, port);
System.out.println("Just connected to play : " +
clientPlay.getRemoteSocketAddress());
System.out.println("SENTS Play BEFORE");
// output streams that write data
OutputStream outToServer = clientPlay.getOutputStream();
DataOutputStream outStreamPlay = new DataOutputStream(outToServer);
outStreamPlay.write(playByteData);
System.out.println("SENTS Play after");
// input streams that read data
InputStream inFromServerPlay = clientPlay.getInputStream();
DataInputStream inStreamPlay = new DataInputStream(inFromServerPlay);
//clientPlay.setSoTimeout(5000);
while ((lstream = inStreamPlay.read(byteArray)) != -1) {
System.out.println("startplay() bytearray -- " +
byteArray.length);
bos.write(byteArray, 0, lstream);
}
inStreamPlay.close();
clientPlay.close();// for closing play socket connection
responseBuffer = bos.toByteArray();
System.out.println("BAOSSIZE " + bos.size());
bos.reset();
bos.flush();
bos.close();
playing = true;
System.out.println("res length -- " + responseBuffer.length);
rcvbb=ByteBuffer.wrap(responseBuffer).order(ByteOrder.LITTLE_ENDIAN).
asShortBuffer().get(playShortData);
playVoiceReceived();// plays received data
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* start playing received the voice data from server
* */
public void playVoiceReceived() {
System.out.println("POOL-4");
try {
if (at != null) {
if (at.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
at.play();// starts playing
} else {
System.out.println("Play BEFORE WRITE");
// Writes the audio data to the audio hardware for playback.
at.write(playShortData, 0, BufferElements2Play);
System.out.println("Play AFTER WRITE");
at.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

The socket has sent the data ... to the local socket send buffer. What happens after that is up to the local TCP stack, the network, the remote TCP stack, and the remote application. If you want to know whether the remote application got the data, it will have to send you a reply.

Operator write does not check whether data was delivered because otherwise it would have to wait for too long time. If network connection is actually down, TCP layer of operating system, will try to send data anyway, but will detect problems somewhat later, i.e. 1 minute later, because it will not receive acknowledgement messages from the opposite side. It will then try to resend data several times, see that problem persists and only then will report exception condition on the socket. To know that socket is in exception condition, you need to perform some operator on socket, i.e. another write attempt. Try doing write in a loop like this:
while (true)
{
outStreamRec.write (data);
Thread.sleep (1000L);
}
It should throw an error about 2 minutes after network will be down.
Note, that in opposite to write operation, operation connect is synchronous, so it actually waits for response from the opposite side, and if there is not respose, it will throw an exception.

Related

Server Socket Isn't Sending Data Back in Java

So, I just learned how to make sockets and all that good stuff in Java, and so my first try got me a message from the client, and then the client crashing. What was supposed to happen was get a message from the client, if that message is equal to this, then send data back. However, the if function for if the message was correct wasn't firing, even though the message was correct.
Even when I remove the if function to check if the string was right or not, the program still freezes up. And by the way, my server is a console application, and my client is a SWT application.
Here's the server code with the removed if function:
try {
System.out.println("Waiting for a connection...");
// Start a server
ServerSocket server = new ServerSocket(3211);
// Listen for anyone at that port
Socket socket = server.accept();
System.out.println("The client has connected!");
// Get the data being sent in
DataInputStream inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
DataOutputStream ouputStream = new DataOutputStream(socket.getOutputStream());
// Turn that into UTF-8
String data = inputStream.readUTF();
System.out.println("Received " + data);
ouputStream.writeUTF("Great!");
System.out.println("Awesome!");
socket.close();
inputStream.close();
ouputStream.close;
server.close();
System.out.println("Socket closed\n-----------------------------");
}
catch(IOException e) {
System.out.println(e);
}
And the client (which is fired when a button gets pressed):
try {
allMessagesTextBox.setText(allMessagesTextBox.getText() + "\nConnecting to the server...");
Socket socket = new Socket("192.168.1.206", 3211);
allMessagesTextBox.setText(allMessagesTextBox.getText() + "\nConnected to the server!");
DataInputStream input = new DataInputStream(System.in);
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
output.writeUTF("sweet");
String data = input.readUTF();
allMessagesTextBox.setText(allMessagesTextBox.getText() + "\nSERVER: " + data);
input.close();
output.close();
socket.close();
}
catch (IOException er) {
allMessagesTextBox.setText(allMessagesTextBox.getText() + "\n" + er);
}
As soon as I press the button to try and start the connection (with the server already running), the client instantly freezes. It doesn't even send any of the "connecting to server" kind of stuff.
Any idea what's going wrong, and how to fix this?
Your client is reading from System.in. It should be reading from the socket input stream.
NB You only need to close the outermost output stream of a socket. That flushes it if necessary and closes the input stream and the socket. You're presently not only closing more than necessary but also in the wrong order,
Your socket is unable to send data because you did not called .flush() method on your outputstream reference. Use this one and you don't have to write flush() and close() method explicitely on streams
Server Code
System.out.println("Waiting for a connection...");
// Start a server
try (ServerSocket server = new ServerSocket(3211)) {
// Listen for anyone at that port
try (Socket socket = server.accept()) {
System.out.println("The client has connected!");
// Get the data being sent in
try (DataInputStream inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()))) {
try (DataOutputStream ouputStream = new DataOutputStream(socket.getOutputStream())) {
// Turn that into UTF-8
String data = inputStream.readUTF();
System.out.println("Received " + data);
ouputStream.writeUTF("Great!");
System.out.println("Awesome!");
}
}
}
System.out.println("Socket closed\n-----------------------------");
} catch (IOException e) {
System.out.println(e);
}
Client Code
try {
allMessagesTextBox.setText(allMessagesTextBox.getText() + "\nConnecting to the server...");
try (Socket socket = new Socket("127.0.0.1", 3211)) {
allMessagesTextBox.setText(allMessagesTextBox.getText() + "\nConnected to the server!");
try (DataInputStream input = new DataInputStream(socket.getInputStream())) {
try (DataOutputStream output = new DataOutputStream(socket.getOutputStream())) {
output.writeUTF("sweet");
}
String data = input.readUTF();
System.out.println(String.format("data received from server '%s':\n", data));
allMessagesTextBox.setText(allMessagesTextBox.getText() + "\nSERVER: " + data);
}
}
} catch (IOException er) {
allMessagesTextBox.setText(allMessagesTextBox.getText() + "\n" + er);
}
Output on Server
Waiting for a connection...
The client has connected!
Received sweet
Awesome!
Socket closed
-----------------------------
Output on Client
data received from server 'Great!':
Now moving to problem in your code.
See the client side code you have written DataInputStream input = new DataInputStream(System.in); instead of DataInputStream input = new DataInputStream(socket.getInputStream())
which causes the failure in receiving message from server

html5 audio GET connection reset by peer on mobile (works fine on PC)

What I'm trying to do is simply send an mp3 file over http/tcp with my own http headers. On the client side I have a webpage with the following line:
<audio src="http://192.168.0.21:14441" controls autoplay loop>
The Java server side has a ServerSocket and accepts basically any connection. It will then send a hardcoded http header followed by the binary data of the mp3-file.
My server class:
public class Server {
private int port = 14441;
private String localIPAddress;
private BufferedReader in;
private BufferedOutputStream out;
private ServerSocket serverSocket;
private Socket clientSocket;
public Server() {
}
public void start() {
new Thread(new Runnable() {
#Override
public void run() {
startAcceptingConnections();
}
}).start();
}
private void startAcceptingConnections() {
tryToOpenPort();//try to open external port with upnp
clientSocket = null;
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
System.err.println("Could not listen on port:" + port);
System.exit(1);
}
System.out.println("Waiting for connection.....");
try {
clientSocket = serverSocket.accept();
System.out.println("Connection successful");
System.out.println("Waiting for input.....");
out = new BufferedOutputStream(clientSocket.getOutputStream());
in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
boolean isSendingMp3 = false;
while ((inputLine = in.readLine()) != null) {
//just output any line the client sends me
System.out.println("Received: " + inputLine);
//Whenever the client sends an empty line this means
//it's ready to receive
if (inputLine.equals("") && !isSendingMp3) {
isSendingMp3 = true;
//Making sure to keep listening to the InputStream
//so I send from a different thread
new Thread(new Runnable() {
#Override
public void run() {
sendMp3File();
}
}).start();
}
}//end of listening to client loop
out.close();
in.close();
clientSocket.close();
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendMp3File() {
try {
//I've tried all sorts of headers
String response = "HTTP/1.x 200 OK\r\n"
+ "Content-Type: audio/mpeg\r\n"
+ "Content-Size: 2911084\r\n"
+ "Range: bytes 0-2911083/2911084\r\n"
+ "X-Content-Duration: 300.1\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Duration: 300.1\r\n"
+ "\r\n";
out.write(response.getBytes(Charset.forName("UTF-8")));
byte[] bytesRaw = new byte[1024 * 10];
InputStream is = new FileInputStream("C:/sample.mp3");
int byteCount = 0;
while ((byteCount = is.read(bytesRaw)) != -1) {
System.out.println("sending bytes:" + byteCount);
out.write(bytesRaw, 0, byteCount);
}
out.flush();
is.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
//Use Cling to open the port via upnp
private void tryToOpenPort() {
try {
localIPAddress = Inet4Address.getLocalHost().getHostAddress();
PortMapping desiredMapping
= new PortMapping(
port,
localIPAddress,
PortMapping.Protocol.TCP,
"Test server"
);
UpnpService upnpService = new UpnpServiceImpl(new PortMappingListener(desiredMapping));
upnpService.getControlPoint().search();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
This always works on a PC browser (Firefox, Chrome, IE) and gives no problems machine to machine (no firewall interference).
However, as soon as I run the webpage from a mobile device (both iOS and Android) the connection is suddenly closed after sending what seems to be a random amount of data. This is somewhere between 0 and 2 seconds after the connection has been established.
The Java application throws the exception:
java.net.SocketException: Connection reset by peer: socket write error
When I profile with Wireshark it shows me everything goes well and then suddenly the client starts sending a bunch of RST messages. I've tried multiple types of headers, even copied a number of headers from existing webservers, but nothing seems to work.
Even simple headers like
"HTTP/1.1 200 OK\r\n"
+ "Content-Type: audio/mpeg \r\n"
+ "\r\n";
Work when I open them from a computer browser, but reset the connection on mobile. Am I forgetting something important?
UPDATE
On mobile browsers it closes the connection after a bit of data has been send. It connects and disconnects again at what seems like random intervals, sometimes with a range in the header and sometimes not. Even when it has received the entire file it will continue to open connections.
I'm guessing some sort of high protocol 'protection' when sending big requests, maybe specifically for when on unstable mobile networks.
Is there some way to bypass this? Whatever it is, it seems a bit unduly.
What happens is that the html5 audio element asks for the first 2 bytes with a range header. When I then (according to rfc2616 validly) ignore this range and send the whole file, the audio player starts behaving as if it's an audio stream (or at-least becomes very confused). This still only happens on mobile browsers somehow.
The solution might be to start accepting range request so that the player doesn't get "confused". I'll post the results as soon as I get the time to try this.
I think the problem is in the code you have not shown. My guess is that you accept the connection and then simple send the response without reading the request. But if the connections gets closed with the request not read this will cause a connection reset. How this reset affects the client depends on the timing, i.e. it might be that the client processed the response before it got the reset or that it found the reset before it had time to process the response.
To fix it you need to read the HTTP request before you sent the response.

Reusing sockets in server-client

I am trying to create a client-server system: my server is a raspberry pi which is running a python webserver on it, and my client is on a different pc and is written is Java. The idea is that the server collects data and when it gets a request from a client, it sends the data to the client.
My client should request the data, wait for 10 seconds and request again etc.
Currently this system is working, but after a day or so, the client starts getting a lot (but not continuously) socket timeouts. I think that this may be the case because for each request I create a new socket for communication and I think that after a day the sockets run out or something like that. This is the code the client executes every 10 seconds:
public static String getData() throws Exception {
TreeSet<Integer> primes = MathUtils.primesSieve(10000);
try {
String data = "";
Socket socket = new Socket(SERVER_ADDRESS, SERVER_PORT);
socket.setReuseAddress(true);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int msg = ColUtils.drawRandomlyWithReplacement(primes, 1, ArrayList::new).get(0);
out.write(msg+"");
out.flush();
String input;
while ((input = in.readLine()) != null) {
data += input;
if (!data.endsWith("#" + prod(msg))) {
throw new Exception("WRONG ECHO");
}
}
socket.close();
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
I tried fixing it by having a socket which is a member of the encapsulating class, but after a singe request the inputstream stopped working. Is there any way where I can keep using a single socket for ALL communications with the server? Or is this the recommended way of doing this sort of communication?
Try first closing the socket and input, output streams. As in your code there is no quarantee that you are releasing the acquired objects.
PrintWriter out = null;
BufferedReader in = null;
Socket socket = null;
try {
...//your statements
} catch (Exception ex) {
//catch or whatever
} finally {
if (out != null) out.close();
if (in != null) in.close();
if (socket != null) socket.close();
}
try to make the Socket object static If possible that would created only once and read the data every 10 sec
Otherwise u can instantiate it before calling the getData method and then read it.
Doing so will make only 1 copy of Socket.
And I don't think u are running out of ports.
The reason might be quit simple that your Program is not receiving the data before the time out. and it is a normal case in a bad network
Socket generally waits indefinitely until it receives data if the timeout is not set Programmatically

datainputstream missing bytes in.read(b)

I'm trying to write a program which acts as a server that will read bytes from a client that is written in PHP - sends request via socket (which i cannot recode due to policy) Here is the server code:
The server runs in: Red Hat Enterprise Linux Server release 6.2 (Santiago)
public void run() {
try {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(0);
while(!isInterrupted) {
try {
Socket server = serverSocket.accept();
LOG.info("Request received from : " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
// DataInputStream in = new DataInputStream(
// new BufferedInputStream(server.getInputStream(), 10000));
byte[] bytes = new byte[10000];
int byteDupLength = in.read(t_bytes);
// in.readFully(bytes); // I tried this but to no avail
// int byteDupLength = bytes.length;
LOG.info(byteDupLength);
byte[] byteDup = new byte[byteDupLength];
System.arraycopy(bytes, 4, byteDup, 0, byteDupLength);
// FOR INFORMATION ONLY
/*for (byte b : byteDup){
LOG.info(b);
}*/
ByteBuffer buffer = ByteBuffer.wrap(byteDup);
LOG.info(buffer);
forwardRequest(byteDup);
server.close();
}
catch(SocketTimeoutException s) {
LOG.error("Socket timed out!", s);
break;
}
catch(IOException e)
{
LOG.error("IOException:", e);
break;
}
}
}
catch (IOException ex) {
LOG.error("Server socket is null", ex);
}
LOG.fatal("ReceiverEngine interrupted!");
}
I encountered a problem when the client sends request consisting of 4948 bytes. The only bytes the server can read is 2090.
Another thing that seems a mystery to me is that, when I run the server via Netbeans in my local (which is a Windows 7 Pro), it works as expected. I dont know what is wrong. Please help.. :)
Thanks!
TCP is a byte stream protocol.
The read() method isn't guaranteed to fill the buffer.
Therefore if you don't receive the expected number of bytes in a single read, you have to loop until you do receive them.
readFully() would have worked if the buffer size agreed with the size of what was sent. In your case you specified a buffer of 10,000 bytes, which weren't sent, so it would have blocked waiting for the other 10000-4948 bytes.

Java - Read file from Socket (while loop never ends)

My JAVA application sends a command to server (command=filename.ini). When the server receives this command it sends filename.ini contents through Socket.
The first problem I had was receiving only partial contents of the file. That happened when in the code I used while(in.available()!=0){//write bytes} because in.available() does not know how big/long the content of the file is. If I use while((numBytesRead = dis.read(buffer)) != -1){//write bytes} the loop will never terminate since the Socket connection remains always open. My question is how else can I terminate the loop once every byte has been received? Please help me I have tried everything. I understand where the mistake is but I don't know how to fix it.
The following is the part of the code I have at the moment:
public class TCPClient {
protected Socket s = null;
public DataInputStream in = null;
public TCPClient(InetAddress ipa, int port) {
Socket s1 = null;
try { //Open the socket.
s1 = new Socket(ipa.getHostAddress(), port);
} catch (IOException ex) {
System.out.println("Error opening socket!");
return;
}
s = s1;
try { //Create an input stream.
in = new DataInputStream(new BufferedInputStream(s.getInputStream()));
} catch (Exception ex) {
System.out.println("Error creating input stream!");
}
}
public synchronized byte[] receive() {
byte[] buffer = new byte[0];
ByteArrayOutputStream getBytes = new ByteArrayOutputStream();
try {
while (in.available() == 0) {
} //Wait for data.
} catch (IOException ex) {
}
try {
int numBytesRead;
buffer = new byte[1024];
while ((numBytesRead = dis.read(buffer, 0, 1024)) != -1) { //LOOP NEVER ENDS HERE BECAUSE CONNECTION IS ALWAYS OPEN
getBytes.write(buffer, 0, numBytesRead);
}
} catch (IOException ex) {
}
return (getBytes.toByteArray());
}
}
You need to define a micro protocol to say the receiver how long is the file, or just close the connection on the server after finishing sending the file. First method is preferred, since it is a little bit more robust. On the client you should have a timeout too in order to avoid to wait forever in case of network problems.
Clarification for micro protocol: before sending the file itself send a 32 (or 64 if needed) bit integer containing the file length. The client should read that integer and then start retrieving the file.

Categories

Resources