sockets long reading data - java

This is my code:
private String receiveData(String sjson) {
Log.i(TAG,"send request: " + sjson);
String jstr="";
try {
OutputStream out = s.getOutputStream();
out.write(sjson.getBytes());
out.flush();
//out.close();
Log.v(TAG,"sended data");
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
char[] cbuf = new char[1];
input.read(cbuf);
String size = new String(cbuf);
while (input.read(cbuf) != 0) {
if((new String(cbuf)).equals("{") == true)
break;
size = size + new String(cbuf);
}
char[] jbuf = new char[Integer.valueOf(size)];
input.read(jbuf);
jstr = "{" + new String(jbuf);
}catch (Exception e) {
Log.e(TAG,e.toString());
}
Log.d(TAG,"responce: " + jstr);
return jstr;
}
public void connectSocket() {
Log.v(TAG,"connecting Socket: "+URL+":"+PORT);
try {
s = new Socket(URL, PORT);
Log.v(TAG,"connect Socket!");
ERROR_CODE = 0;
}catch (Exception e) {
Log.e(TAG,e.toString());
ERROR_CODE = ERROR_SOCKET_CONNECT_SUCCESSFULL;
}
Log.e(TAG,getErrorMsg(ERROR_CODE));
}
public void closeSocket() {
Log.v(TAG,"closeSocket");
try {
s.close();
}catch (Exception e) {
Log.e(TAG,e.toString());
}
}
At server the answer is less than a second. At the client it passes 1 minute before reading data.
Apps stoped at input.read(cbuf); waiting for answer.
Logs:
05-23 06:35:17.540: VERBOSE/Utilits(358): Auth: 77.221.129.100:10598
05-23 06:35:17.660: INFO/Utilits(358): send request: 0119{"data":{"password":"12345","imei":"000000000000001"},"method":"login"}
05-23 06:36:17.909: DEBUG/Utilits(358): responce: {"response":{"success":true,"user":{"id":"6","properties":{"auto":"model":"audi","color":"ffff","number":"td123r"}},"is_driver":"1"}}}
Why does it take so long to read an answer?

What on earth do you expect that method to do? There are bugs in it, and it does things that it should do.
You should specify encoding/charset when you create the InputStreamReader
Why do you read character by character from start to "{"
Why do you create a string for each character that you read before you hit "{"
Why do you append strings in a loop? Use a StringBuilder if you must append.
input.read returns an integer that says how many bytes/character that you have received
It's never guaranteed that it will fill the buffer. So you might not get all data.
Why aren't you closing resources?
.. and now to why it might be slow. Is the server flushing the data? If not, make sure that the server is flushing the data.

Related

No process is on the other end of the pipe - Named Pipes in JAVA

I am using this codes in communicating with Evolis KC200 printer:
#Test
public void studyPipe() {
try {
String echoText = " {\"id\":\"1\",\"jsonrpc\":\"2.0\",\"method\":\"CMD.GetStatus\",\"params\":{\"device\":\"Evolis KC200\"}}";
System.out.println("CMD.GetStatus Request: " + echoText);
String pipeName = "\\\\.\\pipe\\EspfServer00";
RandomAccessFile pipe = new RandomAccessFile(pipeName, "rw");
System.out.println("Writing in pipe: " + echoText + " in pipe "
+ pipeName);
pipe.write(echoText.getBytes("UTF-8"));
// Thread.sleep(1000);
String echoResponse = pipe.readLine();
System.out.println("Response: " + echoResponse);
pipe.close();
} catch (Exception e) {
e.printStackTrace();
}
}
But all I'm getting is this:
java.io.IOException: No process is on the other end of the pipe
at java.io.RandomAccessFile.read0(Native Method)
at java.io.RandomAccessFile.read(RandomAccessFile.java:330)
at java.io.RandomAccessFile.readLine(RandomAccessFile.java:939)
at
They have a test tool built on another language (C#) and their Named Pipe client looks like this:
What is missing in my JAVA codes?
public static string SendRequestPipe(string ip, string port, string request)
{
NamedPipeClientStream objPipeClient;
string answer = string.Empty;
objPipeClient = new NamedPipeClientStream(ip, port, PipeDirection.InOut);
try
{
// Connexion au named pipe ou attente de la disponibilité du named pipe
objPipeClient.Connect(1000);
// Paramétrage de la connexion
objPipeClient.ReadMode = PipeTransmissionMode.Message;
if (objPipeClient.IsConnected == true)
{
// Send request
byte[] datain = Encoding.UTF8.GetBytes(request);
objPipeClient.Write(datain, 0, datain.Length);
// Get answer
int recv = 0;
byte[] data = new byte[1024];
do
{
recv = objPipeClient.Read(data, 0, data.Length);
answer += Encoding.UTF8.GetString(data, 0, recv);
} while (!objPipeClient.IsMessageComplete);
}
}
catch (Exception ex)
{
}
finally
{
objPipeClient.Close();
objPipeClient.Dispose();
}
return answer;
}
I also tried similar approaches in Java but I'm getting the same error.
UPDATE:
I think I know the issue already but I still do not have the resolution.
It seems that the JAVA code is creating another instance of the PIPE that is why it is not receiving any process on that new instance.
I tested with the C# code and it was not creating a new instance.
I checked the instances using this tool:
https://learn.microsoft.com/en-us/sysinternals/downloads/pipelist

unable to find while loops behavior in java

In my application, I have used two while loops for reading the sockets. while loop-1 takes 1% of CPU and while loop-2 takes 100% CPU. I am confused. Please share your valuable thoughts. For more information, I have added two while loops below:
While loop-1:
while(true) {
String message = onReadFinal(in);
if (message != null) {
synchronized (message) {
System.out.println("Message size:" + message);
}
}
}
private String onReadFinal(DataInputStream in) {
String mess = null;
try{
StringBuilder builder = new StringBuilder();
do {
builder.append(in.readInt());
} while(in.available() > 0);
mess = builder.toString();
} catch(IOException e){ e.printStackTrace(); }
return mess;
}
While loop-2:
while(true) {
String message = onRead(in);
if (message != null) {
synchronized (message) {
System.out.println("Message size:" + message);
}
}
}
public String onRead(DataInputStream input) {
String socketmessage = null;
int length;
try {
if(input != null) {
length = input.available();
if(length>0) {
byte[] message = new byte[length];
input.readFully(message, 0, message.length);
socketmessage = new String(message);
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
return socketmessage;
}
Also, if I execute infinite while loop with no statements, it takes 100% of CPU. Someone can you please explain.
if a loop does not contain blocking operations, it always would take 100% CPU.
Your first loop contains blocking operation in.readInt(). Your second loop also contains potentially blocking operation input.readFully(), but calls it only when the stream buffer has enough bytes to read, and so in fact this operation does not block. When there is not enough bytes, the loop immediately repeats non-blocking operation input.available(), without much sense.
You better tell us what you want.

How to make fast data reading using socket in Java?

I'm using SocketChannel for single connection like this:
int sampleBufferSize = 50;
StringBuilder data = new StringBuilder();
ByteBuffer bf = ByteBuffer.allocate(sampleBufferSize);
SocketChannel sc = new SocketChannel();
while(true)
if(sc.read(bf) > 0){
bf.flip();
while(bf.hasRemaining())
data.append((char) bf.get());
bf.clear();
}else{
fireDataReceived(data.toString());
data.delete(0, data.length());
}
This code is not very efficient, but it reads HTTP POST request 130 KB from the same PC in 0.05 seconds. Now I'm trying to write a class with similar functionality but using Socket. Here is the code:
private static final int TIMEOUT_MILLIS = 50;
private boolean reading = false;
private long readBeginTime = 0;
private StringBuilder buffer = new StringBuilder();
private Thread thread = new Thread(){
public void run(){
while(!isInterrupted()){
try {
int b = getInputStream().read();
if(b == -1){
if(reading)
fireDataReceived();
close();
}else{
if(!reading){
reading = true;
readBeginTime = System.currentTimeMillis();
setSoTimeout(TIMEOUT_MILLIS);
}
buffer.append((char) b);
}
} catch (SocketTimeoutException e){
fireDataReceived();
} catch (IOException e) {
e.printStackTrace();
if(reading)
fireDataReceived();
close();
}
}
}
};
private void fireDataReceived(){
BufferedSocketEvent e = new BufferedSocketEvent(this, System.currentTimeMillis() - readBeginTime, buffer.toString());
buffer.setLength(0);
reading = false;
try {
setSoTimeout(0);
} catch (SocketException e1) {
e1.printStackTrace();
}
for(BufferedSocketListener listener: listeners)
listener.dataReceived(e);
}
And the problem is that it takes 0.4 seconds for the same request and I have no idea why does it take so long. Please, explain what is wrong with my code.
The problem with your streams code is that you're reading a byte at a time, which is slow, and also appending to the StringBuilder one at a time, ditto. Try this:
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream());
char[] chars = new char[8192];
int count;
while ((count = in.read(chars)) > 0)
{
buffer.append(chars, 0, count);
fireDataReceived();
}
Note that it isn't correct to use read timeouts as a means to separate requests. You need to parse the data to do that. TCP is a streaming protocol without message boundaries, and there are no guarantees about separate sends being received separately.
You have to use readLine() or similar method. End of HTTP header is marked by empty line. If you don't detect lines you cannot know when to stop reading data. Relying on timeouts or TCP fragments is not a correct solution. If request doesn't contain new line, you need to wait until one appears or the connection is terminated/timed out. You should wait at least a couple of seconds.
I would also get rid of those listeners. Being able to add multiple listeners for single socket might seem like a good idea but the only sensible thing to do with HTTP header is to parse it. The parser also needs to inform the reader when to stop reading.
I would start with something like this:
ServerSocket serverSocket = new ServerSocket(8888);
Socket clientSocket = serverSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "ASCII"));
String[] r = reader.readLine().split(" ");
String type = r[0];
String resource = r[1];
String version = r[2];
Map<String, String> headers = new HashMap<String,String>();
while(true) {
String line = reader.readLine();
if(line.isEmpty()) {
break;
}
String headerLine[] = line.split(":",2);
headers.put(headerLine[0],headerLine[1].trim());
}
processHeader(type, resource, version, headers);

InputStream read() blocks when server returns no input

I am working on a program for Android, which connects to a server via SSH to get some data.
The problem is, in the event a command is sent to the server, that doesn't return anything (such as cat on an empty file), my program hangs, seemingly being blocked by in.read().
I have a breakpoint on the the line
if ((read = in.read(buffer)) != -1){
and on the then/else lines below it. If I debug it, the program breaks normally on the if-statement, but when I hit continue, the program just hangs again, and never makes it to the next breakpoint.
The program works normally if it actually gets a response from the server, but I'd like to protect my program from a hang if the server isn't cooperating properly.
I am using the J2SSH library.
public String command(String command) {
command = command + "\n";
if (session.getSessionType().equals("Uninitialized") || session.isClosed()) {
openShell();
}
OutputStream out = session.getOutputStream();
InputStream in = session.getInputStream();
byte buffer[] = new byte[255];
int read;
String in1 = null;
String fullOutput = "";
try {
try {
out.write(command.getBytes());
} catch (IOException e){
Log.e(TAG,"Error writing IO stream");
e.printStackTrace();
}
boolean retrivingdata = true;
while (retrivingdata){
String iStreamAvail = "Input Stream Available "+ in.available();
if ((read = in.read(buffer)) != -1){
retrivingdata = true;
} else {
retrivingdata = false;
return null;
}
in1 = new String(buffer, 0, read);
fullOutput = fullOutput + in1;
if (read < 255){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return fullOutput;
}
Reading and writing should be done in separate threads. read() is a blocking method that waits until data is available from the server.

Java Sockets and Blackberry programming

i'm new to programming and I'm trying to build a blackberry IRC Client, I made it connect to a server, join a channel and say something, but how can I receive messages ? I don't know how to make a loop to wait for messages, can somebody help me ? here is my code:
package com.rim.samples.device.socketdemo;
import java.io.*;
import javax.microedition.io.*;
import net.rim.device.api.ui.*;
public class ConnectThread extends Thread
{
private InputStream _in;
private OutputStreamWriter _out;
private SocketDemoScreen _screen;
// Constructor
public ConnectThread()
{
_screen = ((SocketDemo)UiApplication.getUiApplication()).getScreen();
}
public void run()
{
StreamConnection connection = null;
String user = "Cegooow";
String channel = "#oi";
try
{
_screen.updateDisplay("Opening Connection...");
String url = "socket://" + _screen.getHostFieldText() + ":6667" + (_screen.isDirectTCP() ? ";deviceside=true" : "");
connection = (StreamConnection)Connector.open(url);
_screen.updateDisplay("Connection open");
_in = connection.openInputStream();
_out = new OutputStreamWriter(connection.openOutputStream());
StringBuffer s = new StringBuffer();
_out.write("NICK " + _screen.getNickText() + "\r\n");
_out.write("USER " + user + "8 * : Java Bot\r\n");
_out.write("JOIN " + channel + "\r\n");
_out.write("PRIVMSG " + channel + " " + _screen.getMessageFieldText() + "\r\n");
_screen.updateDisplay("Done!");
}
catch(IOException e)
{
System.err.println(e.toString());
}
finally
{
_screen.setThreadRunning(false);
try
{
_in.close();
}
catch(IOException ioe)
{
}
try
{
_out.close();
}
catch(IOException ioe)
{
}
try
{
connection.close();
}
catch(IOException ioe)
{
}
}
}
}
I used the sockets demo sample on blackerry jre, thanks
In your code you have an OutputStreamWriter _out to write to the Server, the incoming connection _in (InputStream) is unused. You should expect any incoming data there...
The simplest example I can think of would be like this:
// process the inputstream after writing to _out - in single threaded app
Reader reader = new InputStreamReader(_in);
int data;
while((data = reader.read()) != -1 ){
System.out.println((char) data); // do something with the char
}
reader.close();
In practice, it would be better to use a BufferedReader. Also, if you are building a chat application it might be beneficial to create a new thread to process incoming data and another thread for outgoing data.
Once you get your input stream reader handle you can loop until connection closes
BufferedReader reader = new BufferedReader(_in);
while(true) {
String line = reader.readLine();
// do something...
}

Categories

Resources