i'm trying to communicate with my device through java.
I can communicate with it using telnet, i know that because i use PuTTY, so my configuration is:
ip: 192.168.1.4 port: 2001 communication type: telnet
This works, my device and network is working fine.
So i though that i could do the same through java, then i create this class:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
*
* #author Valter
*/
public class Middleware {
public static void main(String args[]) {
try {
Socket socket = new Socket("192.168.1.4", 2001);
// create a channel between to receive data
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
// create a channel between to send data
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF("}Rv!");
// dataOutputStream.flush();
String answer= dataInputStream.readUTF();
System.out.println("Answer:"+answer);
dataInputStream.close();
dataOutputStream.close();
socket.close();
} catch (UnknownHostException ex) {
System.out.println("EXCEÇÃO UNKNOW HOST EXCEPTION");
} catch (IOException ex) {
System.out.println("EXCEÇÃO IOEXCEPTION");
System.out.println(ex.getMessage());
}
}
}
But when i try to execute this, nothing happens, no exceptions, no nothing.
I looks like a 'while' without end.
What should i do here?
I should use a client telnet to java here?
I don't know what sort of device you're talking to, but if you normally type commands to it using telnet, you're presumably sending newlines to it, and perhaps those newlines are needed as command terminators. So perhaps
dataOutputStream.writeUTF("}Rv!\n");
or
dataOutputStream.writeUTF("}Rv!\r\n");
(along with uncommenting that call to flush()) would work better.
What do you really want to send to the device? DataOutputStream#writeUTF uses a Java specific string encoding and I doubt that this is what the device really expects.
Except for that, if the device is really implementing the telnet protocol properly (and not just something which can be accessed with a telnet client), you have to either use a Java telnet library to support control sequences or implement this yourself. You can't just read and write to the socket as in your example code.
Related
I've been trying to connect to the XTB API and I can't seem to make it work.
I have zero experience with sockets and I'm learning on the go. I'm trying to send the JSON object and I'm expecting some kind of response either a success message or an error but I don't get anything. I don't even know if I'm doing it right.
public static void main(String[] args) {
String host = "xapi.xtb.com";
int port = 5112;
Socket s;
try {
JSONObject main = new JSONObject();
JSONObject user = new JSONObject();
main.put("command", "login");
user.put("userId", "MY_ID");
user.put("password", "MY_PSSWD");
main.put("arguments", user);
s = new Socket(host, port);
SocketAddress a;
a = new InetSocketAddress("xapi.xtb.com", 5112);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
out.write(main.toString());
String response = in.readLine();
System.out.println(response);
in.close();
out.close();
} catch (IOException ex) {
ex.printStackTrace(System.out);
}
}
I only managed to get their WebSocket endpoints to work. That, in addition to the fact that their entire API documentation contains WebSocket commands only, makes me think they expect users to connect that way.
I can't help you with Java, but the algorithm is as follows:
1. Define connection
Get a WebSocket client library / package. Usually first thing you do is to instantiate an object using the wss://... address as parameter. Don't issue the connect command at this stage.
2. Define event handlers
Most WebSocket clients dispatch events which you need to handle in your code.
First event will typically be 'open' and it will be fired once the connection is established. Every message coming from server will fire a 'message' event. You need to write handlers for the 'onOpen' and 'onMessage' events (however the naming convention may be) which will execute your code's logic.
Typically there will be a 'send' command in your WebSocket package that you can use to send messages to the server. Use the command described in the documentation as payload of the send command:
// pseudocode
ws.send({
"command":"login",
"arguments": {
"userId":"1000",
"password":"PASSWORD"
}
})
3. Connect
Once the event handlers are defined, you can issue the 'connect' command.
Good luck with your trading. Hope it helps.
maybe im very, very, very too late but... I have been playing with your example.
You are getting null, because the connection is plain http.
To fix it, you need to change:
import java.net.Socket;
to
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
And then, when creating the socket...
instead of
Socket s
s = new Socket(host, port);
You must put this:
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket s = (SSLSocket) factory.createSocket(host, port);
Also, after out.write.... add
out.flush();
And you are done
Why? in the xtb api docs they said this:
All servers use SSL connection.
And after messing a bit with wireshark, I found that the JSON was sent in plain text...
You may have already found it before, because this question is old, but it remains here in case someone else has the problem
Right now I have a Server.java script that is waiting to establish a connection with a listening port. It is currently running on my Amazon instance.
I also have a Client.java file that is trying to send data to the server that is running locally.
Currently the problem is (and if you know about Amazon cloud you know this) the amazon Ubuntu instance requires a private key to confirm the RSA authentication. Is there someway to do this with the socket? I looked at the constructor and could not find anything to give another argument for the key.
to SSH I have to do this i.e. : ssh -i key.pem root#server.amazonaws.com
Client. java
import java.io.PrintWriter;
import java.net.Socket;
class Client {
public static void main(String args[]) {
String data = "toobie ornaught toobie";
try {
Socket skt = new Socket("my ubuntu instance", 1235);
System.out.print("Server has connected!\n");
PrintWriter out = new PrintWriter(skt.getOutputStream(), true);
System.out.print("Sending string: '" + data + "'\n");
out.print(data);
out.close();
skt.close();
} catch (Exception e) {
System.out.print("Whoops! It didn't work!\n");
}
}
}
You are confused. TCP sockets have nothing to do with ssh (except that ssh does use a TCP socket). RSA keys are needed for SSH. You are just opening a plain TCP socket. The keys and other authentication stuff do not apply.
What you need to do is allow your port number through the firewall which is automatically running on EC2 instances.
Is there a way to have reliable communications (the sender get informed that the message it sent is already received by the receiver) using Java TCP/IP library in java.net.*? I understand that one of the advantages of TCP over UDP is its reliability. Yet, I couldn't get that assurance in the experiment below:
I created two classes:
1) echo server => always sending back the data it received.
2) client => periodically send "Hello world" message to the echo server.
They were run on different computers (and worked perfectly). During the middle of the execution, I disconnected the network (unplugged the LAN cable). After disconnected, the server still keep waiting for a data until a few seconds passed (it eventually raised an exception). Similarly, the client also keep sending a data until a few seconds passed (an exception is raised).
The problem is, objectOutputStream.writeObject(message) doesn't guarantee the delivery status of the message (I expect it to block the thread, keep resending the data until delivered). Or at least I get informed, which messages are missing.
Server Code:
import java.net.*;
import java.io.*;
import java.io.Serializable;
public class SimpleServer {
public static void main(String args[]) {
try {
ServerSocket serverSocket = new ServerSocket(2002);
Socket socket = new Socket();
socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(
inputStream);
while (true) {
try {
String message = (String) objectInputStream.readObject();
System.out.println(message);
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Client code:
import java.net.*;
import java.io.*;
public class SimpleClient {
public static void main(String args[]) {
try {
String serverIpAddress = "localhost"; //change this
Socket socket = new Socket(serverIpAddress, 2002);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(
outputStream);
while (true) {
String message = "Hello world!";
objectOutputStream.writeObject(message);
System.out.println(message);
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
If you need to know which messages have arrived in the peer application, the peer application has to send acknowledgements.
If you want this level of guarantees it sounds like you really want JMS. This can ensure not only that messages have been delivered but also have been processed correctly. i.e. there is no point having very reliable delivery if it can be discarded due to a bug.
You can monitor which messages are waiting and which consumers are falling behind. Watch a producer to see what messages it is sending, and have messages saved when it is down and are available when it restarts. i.e. reliable delivery even if the consumer is restarted.
TCP is always reliable. You don't need confirmations. However, to check that a client is up, you might also want to use a UDP stream with confirmations. Like a PING? PONG! system. Might also be TCP settings you can adjust.
Your base assumption (and understanding of TCP) here is wrong. If you unplug and then re-plug, the message most likely will not be lost.
It boils down on how long to you want the sender to wait. One hour, one day? If you'd make the timeout one day, you would unplug for two days and still say "does not work".
So the guaranteed delivery is that "either data is delivered - or you get informed". In the second case you need to solve it on application level.
You could consider using the SO_KEEPALIVE socket option which will cause the connection to be closed if no data is transmitted over the socket for 2 hours. However, obviously in many cases this doesn't offer the level of control typically needed by applications.
A second problem is that some TCP/IP stack implementations are poor and can leave your server with dangling open connections in the event of a network outage.
Therefore, I'd advise adding application level heartbeating between your client and server to ensure that both parties are still alive. This also offers the advantage of severing the connection if, for example a 3rd party client remains alive but becomes unresponsive and hence stops sending heartbeats.
I would like to add the ability for users to telnet into my app where by they can type in commands etc. I would like a simple Java Telnet server whereby i can provide the authentication strategy.
By "telnet" i am not referring what lib provides telnet connectivity but something a little more. I want the boring protocol stuff done along with a shell that has hooks that i can use to process and execute command lines. Where or what these commands are, is of course my implementation.
This q is not about how to start a socket server or other protocol plumbing type.
In my experience, telnet is telnet, ssh is ssh... if you want the latter then you might look at something like: http://mina.apache.org/sshd/
I've never used it, though.
You could also use the native operating system SSH (if it has it) to tunnel and then run regular telnet on the server. Creating your own telnet access isn't at all complicated if it's just a custom command shell. And as the other poster mentions, there are libraries that make it easy.
...but ssh would be more secure and more straight-forward.
Telnet servers only do telnet.
You might find http://telnetd.sourceforge.net/ suitable.
"Target Audience:
Developers that want to integrate reasonable telnet access into their application."
What exactly do you mean by "telnet into my app where by they can type in commands etc."?
Since both telnet and ssh requires some application to run on the remote machine (most often an instance of a command shell), they really only provide the transport mechanism for the commands. Telnet in particular can be (and has been) abused to send general text-commands over a tcp connection. You can browse the web by using the command telnet www.target-domain.com 80 and manually enter all the http protocol stuff, but i wouldn't recommend it. ssh is just the same, although it adds ssl/tls security to the channel.
Therefore, what I guess you want is something like this:
import java.io.*;
import java.net.*;
public class telnettest {
public static void main(String[] args) throws IOException {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
//Open a listening socket on port 8022 and wait for a connection
echoSocket = new ServerSocket(8022).accept();
System.out.println("connection established");
//Get input and output streams
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (IOException e) {
System.err.println("Couldn't get I/O for "
+ "the connection");
System.exit(1);
}
//Read lines from the input stream (corresponding to user commands)
String userInput;
while ((userInput = in.readLine()) != null) {
//For each line entered, just output it to both remote and local terminal
out.println("echo: " + userInput);
System.out.println("echo: " + userInput);
}
//Clean up connections.
out.close();
in.close();
echoSocket.close();
}
}
which is a shameless edit of this tutorial example.
I'm not sure about ssh login, but I suspect you could get there using javax.net.ssl.SSLServerSocket instead of ServerSocket.
What remains is to do something sensible with the user input, instead of just throwing it back in their faces.
Depeding on the amount of commands and their parameters, you can either do the command parsing yourself, or find a library that handles it for you.
I'm writing a java package that will be called by another language (matlab). If my matlab process ends, I want the Java process to keep running. Whenever matlab starts again, it should be able to communicate with the existing running process. So I think I need to have the Java application communicating through sockets in a client/server model. I envision having a simple set of functions:
startServer(host, port)
runCommand(server, command...)
stopServer(host, port)
I have never done anything like this before. Am I thinking about it in the right way, or is there an easier way of building an application that can run independently of it's parent's process? What's the best modern way of doing this (e.g. are there any good Apache packages)? Can anyone provide a simple demo or point me to a tutorial on communicating with a process through sockets?
[Edit] For some clarification, matlab is able to instantiate a java object and run java code within itself. So the startServer() function in matlab would run java code that will check if a java process is already running on that port and if not, start the server process.
I'm not tied to using sockets by any means (in case it isn't obvious, I'm mostly a matlab developer), so if there's something easier, I'm all for it. I just need to be able to run things independently of matlab, but have matlab control those processes (through java).
The server listens for a connection. When a connection is established by a client. The client can send data. In the current example the client sends the message "Hi my server". To terminate the connection, the client sends the message "bye". Then the server sends the message "bye" too. Finally the connection is ended and the server waits for an other connection. The two programs should be running in the same machine. however if you want to run them in two different machines, you may simply change the address "localhost" by the IP address of the machine where you will run the server.
The server
import java.io.*;
import java.net.*;
public class Provider{
ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message;
Provider(){}
void run()
{
try{
//1. creating a server socket
providerSocket = new ServerSocket(2004, 10);
//2. Wait for connection
System.out.println("Waiting for connection");
connection = providerSocket.accept();
System.out.println("Connection received from " + connection.getInetAddress().getHostName());
//3. get Input and Output streams
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
sendMessage("Connection successful");
//4. The two parts communicate via the input and output streams
do{
try{
message = (String)in.readObject();
System.out.println("client>" + message);
if (message.equals("bye"))
sendMessage("bye");
}
catch(ClassNotFoundException classnot){
System.err.println("Data received in unknown format");
}
}while(!message.equals("bye"));
}
catch(IOException ioException){
ioException.printStackTrace();
}
finally{
//4: Closing connection
try{
in.close();
out.close();
providerSocket.close();
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
}
void sendMessage(String msg)
{
try{
out.writeObject(msg);
out.flush();
System.out.println("server>" + msg);
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
public static void main(String args[])
{
Provider server = new Provider();
while(true){
server.run();
}
}
}
The client
import java.io.*;
import java.net.*;
public class Requester{
Socket requestSocket;
ObjectOutputStream out;
ObjectInputStream in;
String message;
Requester(){}
void run()
{
try{
//1. creating a socket to connect to the server
requestSocket = new Socket("localhost", 2004);
System.out.println("Connected to localhost in port 2004");
//2. get Input and Output streams
out = new ObjectOutputStream(requestSocket.getOutputStream());
out.flush();
in = new ObjectInputStream(requestSocket.getInputStream());
//3: Communicating with the server
do{
try{
message = (String)in.readObject();
System.out.println("server>" + message);
sendMessage("Hi my server");
message = "bye";
sendMessage(message);
}
catch(ClassNotFoundException classNot){
System.err.println("data received in unknown format");
}
}while(!message.equals("bye"));
}
catch(UnknownHostException unknownHost){
System.err.println("You are trying to connect to an unknown host!");
}
catch(IOException ioException){
ioException.printStackTrace();
}
finally{
//4: Closing connection
try{
in.close();
out.close();
requestSocket.close();
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
}
void sendMessage(String msg)
{
try{
out.writeObject(msg);
out.flush();
System.out.println("client>" + msg);
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
public static void main(String args[])
{
Requester client = new Requester();
client.run();
}
}
If you decide to go with a custom socket-level protocol, then I can suggest that you use JBoss Netty at the java end:
In other words, Netty is a NIO client
server framework which enables quick
and easy development of network
applications such as protocol servers
and clients. It greatly simplifies and
streamlines network programming such
as TCP and UDP socket server.
It sounds like you need the Java server process to be independent of the Matlab process. So when the Matlab process starts/stops, the Java server continues. The Java server will sit and wait for incoming connections, and handle multiple connections, disconnects etc.
Here's a tutorial for writing a Java socket server (note it's part of a larger tutorial on Java client/server socket communication).
One challenge you will face (and I can't help you here being Matlab-unaware) is creating or using a platform-independent means of creating the actual message, whether that's using a binary representation, XML (looks like Matlab has some XML functionality) or other.
If, as you say, matlab can run java code from within itself, then there should be no reason that you can't use RMI to communicate between matlab and java server. RMI is vastly easier than raw socket programming.
The easy part is the tutorial: Sun's Sockets Tutorial taught me everything I needed to know about sockets programming, and will hopefully do for you too.
I think you need to clarify your thinking about the commands you want to support, in particular the first and 3rd:
If the Java process isn't running, who's going to respond to your startServer command? And if it is running, who needs it? :)
You can certainly implement a stopServer command. But that would be kind of like having your computer pulling its own power cord out of the wall. We return to the previous question: If the server's stopped, who'll hear the start command?
As I understand it, the only remote operation you need is the middle one.
However... socket programming is only moderately fun. You may consider looking at the RMI tutorial for an alternative.
Any reason that you can't just implement your java server as a collection of servlets in tomcat? Tomcat comes with all the tools to autostart and keep the server running, you can implement SOAP service or RESTful web services pretty easily which will help to decouple your matlab code from your java code.