UPDATE #2: BLUF: I think I found the problem, but I need help figuring out how to fix it. The device needs a command with prefix and suffix STX>command ETX> (I had to drop the open bracket so stackoverflow would show it). When I send over TCP using Hercules (which works), the host interprets STX> and ETX> correctly and just displays "command", however I wrote a java client program that sends the same information but it shows up on the host as "STX>commandETX>". What is java doing differently?
Original:
I've been troubleshooting this for the last few days and I'm out of ideas so here I am. First some background information that may or may not be relevant:
I have a SICK LMS151 LIDAR sensor that I need to access through an Android application. The sensor is designed as a TCP server so you connect as a client and send the command STX>sRN LMDscandataETX>. This cues the sensor to spit a bunch of data back to the client. On a computer I can use a program like Hercules in TCP client mode, send the command and instantly receive the data without issue. However getting an Android app to do the same has been problematic (I've attached the client code below).
I wrote a server app on a separate android device which my client app has been able to connect to and exchange data. I send the command "STX>sRN LMDscandataETX>" through the connection and that's exactly how it shows up on the server side. When the server app sends data, I can see it on my client. However, when I attempt to connect to the sensor with the client, it connects but does not respond to my request for data. Any ideas of issues to look into would be helpful because at this point I'm fresh out. Thanks!
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class TcpClient extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
runTcpClient();
}
private static final int TCP_SERVER_PORT = 2111;
private void runTcpClient() {
try {
Socket s = new Socket("192.168.0.105", TCP_SERVER_PORT);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
Log.i("TcpClient", "Connected!");
//send output msg
String outMsg = "<STX>sRN LMDscandata<ETX>";
out.write(outMsg);
out.flush();
Log.i("TcpClient", "sent: " + outMsg);
//accept server response
String inMsg = in.readLine() + System.getProperty("line.separator");
Log.i("TcpClient", "received: " + inMsg);
//close connection
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UPDATE: Spent some more time on this today. Added a BoundedInputStream from Apache in hopes that maybe I wasn't seeing anything because the sensor wasn't sending a /n character at the end of each reading. Also converted from BufferedReader to Scanner. No luck. I'm fairly convinced now that it's not a problem with my client reading but instead it is somehow sending the command differently from the computer such that it isn't understood by the sensor.
Ok, I solved this issue and I think its worth sharing. After using wireshark I found that the command that worked is substituting STX> and ETX> for \u0002 and \u0003. These are standard TCP headers and footers. I manually went into my code to make the substitution and voila! It worked.
Related
I am using the following code to download a file using Java but i want to detect when connection is lost. I ran the following code and while in the middle of downloading i disconnected my internet purposefully but no exception was thrown and it hanged. Even after turning on the connection back nothing happened. So, it hanged forever without any exceptions. Is there a way to make it throw an exception when the connection is lost? Thanks for the help!
package toplower.top;
import java.io.FileOutputStream;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.*;
import javax.mail.*;
public class testing {
public static void main(String[] args) {
try{
URL website = new URL("http://b128.ve.vc/b/data/128/1735/asd.mp3");
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream("song.mp3");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
}
catch(Exception e){
System.out.println("got here");
e.printStackTrace();
}
System.out.println("Done downloading...");
}
}
apparently one is able to set a timeout on your socket, i think this article describes it : http://technfun.wordpress.com/2009/01/29/networking-in-java-non-blocking-nio-blocking-nio-and-io/
Your current thread blocks forever - and thats your root problem. So one possible solution would be to switch to asynchronous operations and/or to set your timeout
Since you are using HTTP, you would be best of using the Apache HttpClient project. org.apache.http.client.config.RequestConfig.Builder allows to set various timeout values that have no correspondence in java.net.URL and related classes. Especially setting a socket timeout would help in your case. You can then use org.apache.http.HttpEntity.writeTo to directly write the resource to a FileOutputStream.
I need some mechanism that allows me to transfer some data from one java program to another within a same PC. I already investigated RMI but I want 1st app to broadcast some message for 2nd without request of 2nd application. In RMI only client can initiate a communication.
Raw sockets are also not desirable (very low level).
I need something like RMI with a different scheme of starting communication: 1 server broadcasts messages for several clients without requests from clients.
Could you please suggest me some libs/technologies (for desktop app)?
I suggest you to use java messaging service and one of it's implementations such as ApacheMQ.
A good starting point is here.
I would suggest using a database with a trigger and store procedure. Here is an example of calling java methods from the database. A message queue will work, but that is an overly complex solution.
Here's an excerpt from an example of how to create a procedure and call it via a trigger:
First, you add the following Java method to the class DBTrigger
CREATE OR REPLACE PROCEDURE add_emp (
emp_no NUMBER, emp_name VARCHAR2, dept_name VARCHAR2)
AS LANGUAGE JAVA
NAME 'DBTrigger.addEmp(int, java.lang.String, java.lang.String)';
Then, you create the INSTEAD OF trigger:
CREATE OR REPLACE TRIGGER emps_trig
INSTEAD OF INSERT ON emps
FOR EACH ROW
CALL add_emp(:new.empno, :new.ename, :new.dname);
Since you tagged this with CORBA, you could use the Event Service to broadcast a notice to all interested clients.
To enable the server to send packets of information to the client/clients. A datagram, by definition, is “an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed”. Essentially, we are opening a DatagramSocket in order to send DatagramPacket messages to the client. We are using the datagram classes (instead of standard sockets) because they allow us to broadcast information to multiple clients, that are all connected to a MulticastSocket.
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class MulticastSocketServer {
final static String INET_ADDR = "224.0.0.3";
final static int PORT = 8888;
public static void main(String[] args) throws UnknownHostException, InterruptedException {
// Get the address that we are going to connect to.
InetAddress addr = InetAddress.getByName(INET_ADDR);
// Open a new DatagramSocket, which will be used to send the data.
try (DatagramSocket serverSocket = new DatagramSocket()) {
for (int i = 0; i < 100; i++) {
String msg = "Sent message no " + i;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(),
msg.getBytes().length, addr, PORT);
serverSocket.send(msgPacket);
System.out.println("Server sent packet with msg: " + msg);
Thread.sleep(500);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
One thing that we need to take into consideration here, is that there are specific addresses that allow us to use a MulticastSocket are limited, specifically in the range of 224.0.0.0 to 239.255.255.255. Some of them are reserved, like 224.0.0.0. The address that we are using, 224.0.0.3, can be used safely.
Regarding the client, we are going to move a little bit differently. We are going to create a client class, that will accept incoming messages from the server, and then we are going to duplicate this class. The point here is that by using the same code, we can connect to the server seamlessly, while having as many clients as we like.
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
public class MulticastSocketClient
{
final static String INET_ADDR = "224.0.0.3";
final static int PORT = 8888;
public static void main(String[] args) throws UnknownHostException {
// Get the address that we are going to connect to.
InetAddress address = InetAddress.getByName(INET_ADDR);
// Create a buffer of bytes, which will be used to store
// the incoming bytes containing the information from the server.
// Since the message is small here, 256 bytes should be enough.
byte[] buf = new byte[256];
// Create a new Multicast socket (that will allow other sockets/programs
// to join it as well.
try (MulticastSocket clientSocket = new MulticastSocket(PORT)){
//Joint the Multicast group.
clientSocket.joinGroup(address);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf, buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
First, we start the clients, which will keep waiting for incoming packets of information. As soon as we start the server, it will send the information packets and the clients will receive them and print the information on the screen
ZeroMQ could be what you are searching, but I have only used it in C, C++ and Python, so I am not totally sure of how well it is usable in Java. But they have implemented the Publisher-Subscriber pattern for their sockets and at least the static library of the version 3.2.2 under ubuntu 12.04 is stable and works very well.
As a "quick fix" write the output to file and have the second app read the file.
This is not elegant at all, but if you code to interfaces you can later replace the implementation with something better.
A good solution would be an implementation of the OMG Data Distribution Standard (DDS). With DDS there is just a global data space with a dynamic discovery protocol. See for example RTI DDS, there is a free community edition.
Hi ive written some code to connect to a server through the use of a socket. Id like to write some simple code that allows me to send a string to the server, im assuming this will involve input and output streams but I am new to this. Ive put the code I am working with below, any insights into the best way to accomplish this would be great.
import java.net.*;
import java.io.*;
public class SocketMarket
{
public static void main(String [] args)
{
String serverName = "XX.X.X.XXX";
int port = XXXX;
try
{
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Connected to " + client.getRemoteSocketAddress());
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
Thanks in advance
client.getOutputStream().write("Hello World".getBytes());
client.getOutputStream().flush();
The above is how you would send just a String, but you will probably want to build up some infrastructure around sending arbitrary text.
The general idea is that your server and client will communicate with each other using InputStream's and OutputStream's, which can be accessed from a Socket via getInputStream() and getOutputStream(), once the connection between them is made.
For your server to receive connections, you should be using a ServerSocket to accept() incoming connections.
Insight is here, the "really big index" for java.
http://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html
Yes, it involves OutputStreams. If you want to output Strings you could write raw bytes via the OutputStream you get from the connection but then you completely loose control over encoding. You need to learn about reader/writer/streams first, then networking via sockets is simple. You can find the relevant part of the Java tutorials here: http://docs.oracle.com/javase/tutorial/essential/io/ (you can ignore the NIO part completely for the beginning). After that you can learn about socket networking: http://docs.oracle.com/javase/tutorial/networking/sockets/index.html .
So I found out how to connect the Arduino to my java program. But using the serial connections doesn't give any useful data back, its either in the wrong format, or just sends it as a box. I've looked at the related questions posted early in here, but none of the tips seems to help. So does anyone know how to send the data between an Arduino and a computer using the serial port?
This is the code I'm using, provided by this person:
http://silveiraneto.net/2009/03/01/arduino-and-java/
package serialtalk;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import java.io.InputStream;
import java.io.OutputStream;
import processing.app.Preferences;
public class Main {
static InputStream input;
static OutputStream output;
public static void main(String[] args) throws Exception{
Preferences.init();
System.out.println("Using port: " + Preferences.get("serial.port"));
CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(
Preferences.get("serial.port"));
SerialPort port = (SerialPort)portId.open("serial talk", 4000);
input = port.getInputStream();
output = port.getOutputStream();
port.setSerialPortParams(Preferences.getInteger("serial.debug_rate"),
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
while(true){
while(input.available()>0) {
System.out.print((char)(input.read()));
}
}
}
}
The Arduino is this:
http://www.arduino.cc/en/Main/ArduinoBoardDuemilanove
The code simply receives a number, and determines which analog reading it should be sending back, from my Arduino.
When dealing with serial connections make sure of the following key points:
BAUD Rates match
DATABITS should match
STOPBITS should match
PARITY should match
Make sure you are using the correct cable (Null modem if needed)
Make sure the cable run isn't too long
All of the above can cause odd stuff to come out of the com port on the Java side. Once you get the hang of this it gets much easier.
My personal favorite library here.
I have this small test socket connection class:-
import java.net.Socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
public class TestTelnet {
public static void main(String args[]) throws Exception {
Telnet telnet = new Telnet();
Socket socket = null ;
socket = new Socket("localhost", 23);
socket.setKeepAlive(true);
BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
System.out.println(r.readLine());
socket.close();
}
}
It works perfectly well when I use another port (for example 25 for SMTP) and the println of r.readLine works brilliantly. I can also connect to port 23 via the command prompt (telnet localhost 23) and I get the following returned:-
Ubuntu 8.10
my-laptop login:
But when I try and connect to port 23 using my java class, it just hangs on the readLine println. Does anyone know why this is?
I guess it's because your expecting a line (with CR or CRLF termination) but your telnet service does not send a complete line. Try using r.read() instead of r.readLine()
Telnet is a protocol, and is probably expecting you to do option negotiation. Once you send it something useful, it will probably send you something useful.
see: http://www.faqs.org/rfcs/rfc854.html
Telnet is both a protocol and an application
When you use telnet the application to a machine, the application sends the protocol information so the remote machine may respond.
Since you say it stay there, it means it is working, it's just you are not following the protocol.
The protocol is described here:
https://www.rfc-editor.org/rfc/rfc854
What you're trying to do here is write a telnet application.
A good example of a Telnet client can be found at http://www.java2s.com/Code/Java/Network-Protocol/ExampleofuseofTelnetClient.htm