this code is giving me some problems. This's simply the thread portion of a Service that receive data sent trough a TCP connection. This data is an image (160x120x16bpp = 38400 bytes) feed to an Activity trough a callback.
public void run() {
InetAddress serverAddr;
link_respawn = 0;
try {
serverAddr = InetAddress.getByName(VIDEO_SERVER_ADDR);
} catch (UnknownHostException e) {
Log.e(getClass().getName(), e.getMessage());
e.printStackTrace();
return;
}
Socket socket = null;
DataInputStream stream;
do {
bad_frames = 0;
frames = 0;
status = FrameDecodingStatus.Idle;
try {
socket = new Socket(serverAddr, VIDEO_SERVER_PORT);
stream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
final byte[] _data = new byte[PACKET_SIZE];
final byte[] _image_data = new byte[IMAGE_SIZE];
int _data_index = 0;
while (keepRunning) {
if (stream.read(_data, 0, _data.length) == 0)
continue;
for (byte _byte : _data) {
if (status == FrameDecodingStatus.Idle) {
if (_byte == SoF) {
status = FrameDecodingStatus.Data;
_data_index = 0;
}
} else if ((status == FrameDecodingStatus.Data) && (_data_index < IMAGE_SIZE)) {
_image_data[_data_index] = _byte;
_data_index++;
} else if ((status == FrameDecodingStatus.Data) && (_data_index == IMAGE_SIZE)) {
if (_byte == EoF) {
if(frameReadyCallBack!=null)
frameReadyCallBack.frameReady(_image_data);
frames++;
status = FrameDecodingStatus.Idle;
}
}
}
}
link_respawn++;
Thread.sleep(VIDEO_SERVER_RESPAWN);
Log.d(getClass().getName(), "Link respawn: " + link_respawn);
} catch (Throwable e) {
Log.e(getClass().getName(), e.getMessage());
e.printStackTrace();
}
} while (keepRunning);
if (socket != null) {
try {
socket.close();
} catch (Throwable e) {
Log.e(getClass().getName(), e.getMessage());
e.printStackTrace();
}
}
}
the Android Activity that receive the callback find data in array corrupted in a very strange way .. i.e. starting at a certain index data into array is set to 0.
How can I avoid this?
read is not readFully. Three-arg read returns the number of bytes that has been read, which is not necessary the full length of the array supplied.
This codes drops the read return value and process the entire array.
if (stream.read(_data, 0, _data.length) == 0)
continue;
for (byte _byte : _data) {
Related
I'm trying to download files in java in a multi-segment way (i.e., dividing it to several parts and downloading each part in a separate thread parallelly) but when I use the code below, it seems each thread is downloading the whole file instead of just a part of it but when it finishes, file is downloaded correctly.
note that "downloadedSizeCombined" is sum of all bytes which are downloaded by all the threads and ArrayList "downloadedSize" keeps track of bytes which are downloaded by a single thread.
this method is in class Download which extends SwingWorker.
public Void doInBackground() {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < MAX_NUMBER_OF_PARTS; i++) {
int numOfThePart = i;
es.execute(new Runnable() {
#Override
public void run() {
RandomAccessFile file = null;
InputStream stream = null;
try {
while (Download.this.getStatus() == WAITINGLIST) {
Thread.sleep(1);
}
// Open connection to URL.
HttpURLConnection connection =
(HttpURLConnection) url.openConnection();
// Specify what portion of file to download.
int startByte = numOfThePart * sizeOfFile / MAX_NUMBER_OF_PARTS;
int endByte = ((numOfThePart + 1) * sizeOfFile / MAX_NUMBER_OF_PARTS) - 1;
if (numOfThePart == MAX_NUMBER_OF_PARTS)
endByte = ((numOfThePart + 1) * sizeOfFile / MAX_NUMBER_OF_PARTS);
connection.setRequestProperty("Range",
"bytes=" + ((startByte + downloadedSize.get(numOfThePart))) + "-" + endByte);
// Connect to server.
connection.connect();
// Check for valid content length.
int contentLength = connection.getContentLength();
if (contentLength < 1) {
System.out.println("1");
}
/* Set the size for this download if it
hasn't been already set. */
if (sizeOfFile == -1) {
sizeOfFile = contentLength;
}
file = new RandomAccessFile(new File(s.getCurrentDirectory(), getFileName(url)),
"rw");
file.seek(startByte + downloadedSize.get(numOfThePart));
fileLocation = new File(s.getCurrentDirectory(), getFileName(url));
stream = connection.getInputStream();
while (status == CURRENT) {
file.seek(startByte + downloadedSize.get(numOfThePart));
byte buffer[];
buffer = new byte[MAX_BUFFER_SIZE];
// Read from server into buffer.
int read = stream.read(buffer);
if (read == -1)
break;
// Write buffer to file.
file.write(buffer, 0, read);
downloadedSizeCombined += read;
downloadedSize.set(numOfThePart, downloadedSize.get(numOfThePart) + read);
publish(numOfThePart);
while (status == PAUSED) {
Thread.sleep(1);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// Close file.
if (file != null) {
try {
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// Close connection to server.
if (stream != null) {
try {
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
});
}
return null;
}
Thanks in advance.
Can't we use UDP connection? So if we use DatagramSocket class, it will anyways send the data in packets. Try this.
Will get back on this soon..
I'm trying to send and read the reply from the socket with no luck. What I got so far is, connected to the server and read connection reply (header from Ericsson telco exchange) and printed it on System.out. What I need to be able to do is send a command to the exchange and get the reply and that's where I'm stuck. Below is my test code.
Any help is appreciated.
public class ExchangeClientSocket {
public void run() {
try {
int serverPort = 23;
InetAddress host = InetAddress.getByName("my.host.ip.address");
Socket socket = new Socket(host, serverPort);
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(isr);
int i;
StringBuffer buffer = new StringBuffer();
while (true) {
i = in.read();
if (i == 60) {
break;
} else {
buffer.append((char) i);
}
}
// this returns the head from exchange
System.out.println(buffer.toString());
out.write("allip;"); // command I want to send to exchange
out.flush();
System.out.println(in.ready()); // this returns false
System.out.println(in.read());
System.out.println("damn..");
buffer = new StringBuffer();
// can't get into this loop
// this is where I want to read the allip response
while ((i = in.read()) != -1) {
i = in.read();
if (i == 60) {
break;
} else {
buffer.append((char) i);
}
}
System.out.println(buffer.toString());
out.close();
in.close();
socket.close();
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is a suggestion on how to get input from the server after writing to the output stream: simply get another input stream from the socket.
So instead of reading from the same stream you create a new stream from the socket after you sent the command and read it.
I would therefore suggest to change your code to this here:
public void run() {
try {
int serverPort = 23;
InetAddress host = InetAddress.getByName("my.host.ip.address");
Socket socket = new Socket(host, serverPort);
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(isr);
int i;
StringBuffer buffer = new StringBuffer();
while (true) {
i = in.read();
if (i == 60) {
break;
} else {
buffer.append((char) i);
}
}
// this returns the head from exchange
System.out.println(buffer.toString());
out.write("allip;"); // command I want to send to exchange
out.flush();
// Create a new input stream here !!!
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
buffer = new StringBuffer();
// can't get into this loop
while ((i = in.read()) != -1) {
i = in.read();
if (i == 60) {
break;
} else {
buffer.append((char) i);
}
}
System.out.println(buffer.toString());
out.close();
in.close();
socket.close();
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
My problem is that I need to control mobile robot E-puck via Bluetooth in Java, by sending it commands like "D,100,100" to set speed, "E" to get speed, and etc. I have some code:
String command = "D,100,100";
OutputStream mOutputToPort = serialPort.getOutputStream();
mOutputToPort.write(command.getBytes());
So with this method write I can only send byte[] data, but my robot won't understand that.
For example previously I have been using this commands on Matlab like that:
s = serial('COM45');
fopen(s);
fprintf(s,'D,100,100','async');
Or on program Putty type only:
D,100,100 `enter`
Additional info:
I've also figured out, that Matlab has another solution for same thing.
s = serial('COM45');
fopen(s);
data=[typecast(int8('-D'),'int8') typecast(int16(500),'int8') typecast(int16(500),'int8')];
In this case:
data = [ -68 -12 1 -12 1];
fwrite(s,data,'int8','async');
Wouldn't it be the same in Java:
byte data[] = new byte[5];
data[0] = -'D';
data[1] = (byte)(500 & 0xFF);
data[2] = (byte)(500 >> 8);
data[3] = (byte)(500 & 0xFF);
data[4] = (byte)(500>> 8);
And then:
OutputStream mOutputToPort = serialPort.getOutputStream();
mOutputToPort.write(data);
mOutputToPort.flush();
Main details in code comments. Now you can change wheel speed by typing in command window D,1000,-500 and hitting enter.
public class serialRobot {
public static void main(String[] s) {
SerialPort serialPort = null;
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier("COM71");
if (portIdentifier.isCurrentlyOwned()) {
System.out.println("Port in use!");
} else {
System.out.println(portIdentifier.getName());
serialPort = (SerialPort) portIdentifier.open(
"ListPortClass", 300);
int b = serialPort.getBaudRate();
System.out.println(Integer.toString(b));
serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.setInputBufferSize(65536);
serialPort.setOutputBufferSize(4096);
System.out.println("Opened " + portIdentifier.getName());
OutputStream mOutputToPort = serialPort.getOutputStream();
InputStream mInputFromPort = serialPort.getInputStream();
PerpetualThread t = readAndPrint(mInputFromPort);
inputAndSend(mOutputToPort);
t.stopRunning();
mOutputToPort.close();
mInputFromPort.close();
}
} catch (IOException ex) {
System.out.println("IOException : " + ex.getMessage());
} catch (UnsupportedCommOperationException ex) {
System.out.println("UnsupportedCommOperationException : " + ex.getMessage());
} catch (NoSuchPortException ex) {
System.out.println("NoSuchPortException : " + ex.getMessage());
} catch (PortInUseException ex) {
System.out.println("PortInUseException : " + ex.getMessage());
} finally {
if(serialPort != null) {
serialPort.close();
}
}
}
private static PerpetualThread readAndPrint(InputStream in) {
final BufferedInputStream b = new BufferedInputStream(in);
PerpetualThread thread = new PerpetualThread() {
#Override
public void run() {
byte[] data = new byte[16];
int len = 0;
for(;isRunning();) {
try {
len = b.read(data);
} catch (IOException e) {
e.printStackTrace();
}
if(len > 0) {
System.out.print(new String(data, 0, len));
}
}
}
};
thread.start();
return thread;
}
private static void inputAndSend(OutputStream out) {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int k = 0;
for(;;) {
String komanda;
try {
komanda = in.readLine();
} catch (IOException e) {
e.printStackTrace();
return;
}
komanda = komanda.trim();
if(komanda.equalsIgnoreCase("end")) return;
byte komandaSiust[] = proces(komanda); //Command we send after first
//connection, it's byte array where 0 member is the letter that describes type of command, next two members
// is about left wheel speed, and the last two - right wheel speed.
try {
if(k == 0){
String siunc = "P,0,0\n"; // This command must be sent first time, when robot is connected, otherwise other commands won't work
ByteBuffer bb = ByteBuffer.wrap(siunc.getBytes("UTF-8"));
bb.order(ByteOrder.LITTLE_ENDIAN);
out.write(bb.array());
out.flush();
}else{
ByteBuffer bb = ByteBuffer.wrap(komandaSiust);
bb.order(ByteOrder.LITTLE_ENDIAN);
out.write(bb.array());
out.flush();
}
k++;
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
private static byte[] proces(String tekstas){
tekstas = tekstas.trim();
char[] charArray = tekstas.toCharArray();
byte kodas1[];
int fComa = tekstas.indexOf(',', 1);
int sComa = tekstas.indexOf(',', 2);
int matavimas = charArray.length;
int skir1 = sComa - fComa - 1;
int skir2 = matavimas - sComa -1;
char leftSpeed[] = new char[skir1];
for(int i = 0; i < skir1; i++){
leftSpeed[i] = charArray[fComa + i + 1];
}
char rightSpeed[] = new char[skir2];
for(int i = 0; i < skir2; i++){
rightSpeed[i] = charArray[sComa + i + 1];
}
String right = String.valueOf(rightSpeed);
String left = String.valueOf(leftSpeed);
int val1 = Integer.parseInt(left);
int val2 = Integer.parseInt(right);
kodas1 = new byte[5];
kodas1[0] = (byte)-charArray[0];
kodas1[1] = (byte)(val1 & 0xFF);
kodas1[2] = (byte)(val1 >> 8);
kodas1[3] = (byte)(val2 & 0xFF);
kodas1[4] = (byte)(val2 >> 8);
return kodas1;
}
private static class PerpetualThread extends Thread {
private boolean isRunning = true;
public boolean isRunning() { return isRunning; }
public void stopRunning() {
isRunning = false;
this.interrupt();
}
}
}
According to the documentation, you need to call setSerialPortParams(int baudrate, int dataBits, int stopBits, int parity) on your serial port.
I have some problem with Java IO, this code below is not working, the variable count return -1 directly.
public void putFile(String name, InputStream is) {
try {
OutputStream output = new FileOutputStream("D:\\TEMP\\" + name);
byte[] buf = new byte[1024];
int count = is.read(buf);
while( count >0) {
output.write(buf, 0, count);
count = is.read(buf);
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
But if I commented the OutputStream such as
public void putFile(String name, InputStream is) {
try {
//OutputStream output = new FileOutputStream("D:\\TEMP\\" + name);
byte[] buf = new byte[1024];
int count = is.read(buf);
while( count >0) {
//output.write(buf, 0, count);
count = is.read(buf);
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
The count will return the right value (>-1).
How is this possible ? Is it a bug ?
I'm using Jetty in Eclipse with Google plugins and Java 6.21 in Windows 7.
PS :I change the original code, but it doesn't affect the question
I'm trying to get a live flash that lives on a webserver to talk to a local java server, that will live on the clients PC.
I'm trying to achieve this with a socket connection. (port 6000)
Now, at first flash was able to connect, but it just sends <policy-file-request/>. After this nothing happens.
Now, some people at Kirupa suggested to send an cross-domain-policy xml as soon as any connection is established from the java side. http://www.kirupa.com/forum/showthread.php?t=301625
However, my java server just throws the following:
End Exception: java.net.SocketException: Software caused connection abort: recv failed
I've already spend a great amount of time on this subject, and was wondering if anyone here knows what to do?
I found the anwser, So ill post it here in case someone with a simmilar question finds this post.
The moment Flash connects to a local socket server it will send the following:
<policy-file-request/>
We will have to answer with a policy file and immediatly close the connection.
Java:
import java.net.*;
import java.io.*;
public class NetTest {
public static void main(String[] args) {
ServerSocket serverSocket = null;
/* Open a socket to listen */
try {
serverSocket = new ServerSocket(6000);
} catch (IOException e) {
System.out.println("Could not listen on port: 6000");
System.exit(-1);
}
// Try catch a socket to listen on
Socket clientSocket = null;
try {
System.out.println("Waiting for auth on 6000...");
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.out.println("Accept failed: 6000");
System.exit(-1);
}
// Now a stream has been opened...
InputStream in = null;
OutputStream out = null;
try {
in = clientSocket.getInputStream();
out = clientSocket.getOutputStream();
} catch (IOException e) {
System.out.println("Failed to get streams.");
System.exit(-1);
}
System.out.println("Socket connection incoming!");
// Keep going while we can...
byte b[] = new byte[100];
int offset = 0;
String s;
try {
boolean done = false;
boolean auth = false;
String protocol_target = "<policy-file-request/>";
byte[] p_bytes = protocol_target.getBytes();
int result;
while (!done) {
if (in.read(b, offset, 1) == -1)
done = true;
else {
if (!auth) {
++offset;
b[offset] = 0;
if (offset != p_bytes.length) {
System.out.println("Waiting for protocol data... ("
+ offset + "/" + p_bytes.length + ")");
} else {
// Compare byte data
for (int i = 0; i < p_bytes.length; ++i) {
System.out.print(b[i] + " ");
}
System.out.print("\n");
System.out.flush();
for (int i = 0; i < p_bytes.length; ++i) {
System.out.print(p_bytes[i] + " ");
}
System.out.print("\n");
System.out.flush();
boolean match = true;
for (int i = 0; i < p_bytes.length; ++i) {
if (b[i] != p_bytes[i]) {
match = false;
System.out
.println("Mismatch on " + i + ".");
}
}
if (match)
auth = true;
else {
System.out.println("Bad protocol input.");
System.exit(-1);
}
}
// Auth
if (auth) {
System.out.println("Authing...");
s = "<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain='*' to-ports='6000' /></cross-domain-policy>";
b = s.getBytes();
out.write(b, 0, b.length);
b[0] = 0;
out.write(b, 0, 1); // End
out.flush();
offset = 0;
b = new byte[100];
b[0] = 0;
auth = true;
System.out.println("Auth completed.");
}
}
}
}
} catch (IOException e) {
System.out.println("Stream failure: " + e.getMessage());
System.exit(-1);
}
// Finished.
try {
in.close();
out.close();
clientSocket.close();
} catch (Exception e) {
System.out.println("Failed closing auth stream: " + e.getMessage());
System.exit(-1);
}
// Try catch a socket to listen on for data
try {
System.out.println("Waiting on 6000 fo data...");
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.out.println("Accept failed: 6000");
System.exit(-1);
}
// Now a stream has been opened...
in = null;
out = null;
try {
in = clientSocket.getInputStream();
out = clientSocket.getOutputStream();
} catch (IOException e) {
System.out.println("Failed to get streams.");
System.exit(-1);
}
System.out.println("Socket data connection waiting.");
// Echo
try {
boolean done = false;
while (!done) {
if (in.read(b, offset, 1) == -1)
done = true;
else {
b[1] = 0;
s = new String(b);
System.out.print(s);
System.out.flush();
}
}
} catch (IOException e) {
System.out.println("Failed echo stream: " + e.getMessage());
System.exit(-1);
}
// Finished.
try {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
} catch (Exception e) {
System.out.println("Failed closing stream: " + e.getMessage());
System.exit(-1);
}
}
}