How to connect to a broker API using sockets and Java? - java

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

Related

Pass 'host parameter' to ServerSocket in java

I am currently working under proxy server (the core was taken from here https://resources.oreilly.com/examples/9781565923713/blob/master/SimpleProxyServer.java)
But, this example uses launch parameters, when I want to pass host directly from the client.
Client is a HTTP connection like that
final HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com")
.openConnection(
new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7901)));
conn.connect();
System.out.println(conn.getResponseCode());
My initial idea was to read client's request, store it as String (or byty[]), fetch header's "Host:" parameter and pass it to server.
However, SimpleProxyServer.java uses while((bytes_read = from_client.read(request)) != -1) in the Thread that sends data to server, and code hangs on that moment if I read InputSream to get host before this t thread was started.
I am talking about something like this
InputStreamReader from_client_reader = new InputStreamReader(client.getInputStream());
BufferedReader reader = new BufferedReader(from_client_reader);
String line = reader.readLine();
while (!line.isEmpty()) {
line = reader.readLine();
if (line.contains("Host: ")) {
host = line.substring(line.indexOf("Host: ") + 6,
line.length()).trim().replace("www.", "");
}
}
Right before creating of the connection try { server = new Socket(host, remoteport); }
The question is: "Is there other ways on how to pass parameters to Socket or how to create Proxy server that launches Socket using request parameters from the client?"
Well, if someone ever wonders, I decided to create another small Socket server that listens for commands from client, and launches process (java -jar ProxyServer.jar <...>) through Runtime. Also, kills this process if necessary.
Basically, client has to send two requests: one to setup Proxy server, another to connect to the proxy server.
I am sure there is a better solution for this, however, this one suits me.

Java.Nio - ByteBuffer give weird character in json string type message

I have Java Client-Server application I built using standard java.io (Socket and ServerSocket). In both server and client, I use DataInputStream to read the message using readUTF and DataOutputStream to write the message using writeUTF. I use thread-per-connection architecture for this application.
I have an additional feature that I need to add now, which is allowing a client to have a persistent connection open to the server and always listening to what server will write. I found out, with my current thread-per-connection architecture, my application won't scale because it holds the thread when the client opens the persistent connection.
I did some research and think to refactor my server to use java.nio (SocketChannel and ServerSocketChannel). I try to make it compatible with the client (so I don't need to change the client). This is when the problem occurs because I need to change from readUTF method to using ByteBuffer class to read the message, now I got a weird character in my message.
This is my message that works before using readUTF (Server) that come from writeUTF (Client)
{"command":"PUBLISH","resource":{"name":"","description":"","tags":[]}
When I sent the same message to my new server, I got this in my read method
�{"command":"PUBLISH","resource":{"name":"","description":"","tags":[]}
My read method is:
else if (clientKey.isReadable()) {
SocketChannel clientSocket = (SocketChannel) clientKey.channel();
ByteBuffer buffer = ByteBuffer.allocate(4096);
clientSocket.read(buffer);
String message = new String(buffer.array());
Logger.debug(message);
clientSocket.register(selector, SelectionKey.OP_WRITE);
}
This is how I write the message from client:
try (Socket echoSocket = new Socket(hostName, portNumber);
DataOutputStream streamOut = new DataOutputStream(echoSocket.getOutputStream());) {
streamOut.writeUTF(message.toJson());
}
toJson() is just a method to convert java object to JSON string and I use Jackson library to do that.
I have tried to remove it using regex and Normalizer library but it won't work.
Is there anyone experience the same things and solve it?

Building a Rest Server

I've learned how to send and handle Rest API requests, so am reasonably comfortable with how an outside user would submit requests to an API through methods such as opening a connection to the API, setting a request method and processing returned messages.
However the time has come to create my own Rest Web Service, and I'm a bit stuck as I'm not entirely familiar with just how the server will handle the communication.
I can set up a connection just fine to allow for communication, but I'm not particularly comfortable with the specifics of a connection.
Below is the method where I initialise the server, which will then wait until something connects and have a brief conversation until the client disconnects.
public void Initialise(){
try {
ServerSocket s = new ServerSocket(21); //TODO: Change port?
while(true){
Socket incoming = s.accept();
Runnable r = new ConnectionManager(incoming);
Thread t = new Thread(r);
t.start();
}
}
catch(IOException e){
e.printStackTrace();
}
}
And the class handling the connection.
public class ConnectionManager implements Runnable{
private Socket incoming;
public ConnectionManager(Socket i){
this.incoming = i;
}
#Override
public void run() {
try{
try{
//Initialise IOStreams
InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();
Scanner in = new Scanner(inStream);
PrintWriter out = new PrintWriter(outStream, true);
out.println("TODO: Change this message. Press Q to quit.");
boolean done = false;
while (!done && in.hasNextLine()){
String line = in.nextLine();
out.println("Echo: " +line);
if (line.trim().equals("Q")){
done = true;
}
}
}
finally{
incoming.close();
}
}
catch (IOException e){
e.printStackTrace();
}
}
}
What I'm not sure of how to do, is how I start building an application that listens for Rest requests, and then processes them accordingly. I feel confident that upon examining the connection, I'd be able to engineer functionality to process the API request, however I do not know how to view the specifics of a Rest request sent by a user.
For example, if a user were to send a request, such as
GET exampleAPI/endpoint?params
How do I examine the request, and then subsequently process it accordingly?
For example, on the client side when you initiate the request, an approach such as the use of HttpURLConnection would allow you to follow the process of
HttpURLConnection c = (HttpURLConnection) targetURL.openConnection();
c.setRequestMethod("GET");
Which would allow you to submit a Get request to the target URI.
Looking through the Java Documentation for Socket, I don't quite know how I can view incoming requests and active connections.
Am I missing something, or just doing things completely wrong?
As I mentioned in my comments, you can use Jersey/Spring/etc.. for this rather than you rewriting the logic for the whole server and handling multiple threads, etc..
Also, you should know that there is a JDK API called JAX-RS (specification plus implementation) for the same. you can look here
You can look here for Spring REST Controller or here for Jersey.
I recommend you go through JDK JAX-RS API first, then you may have a look at Spring and Jersey.
There are other vendors implementing JAX-RS, which you may be interested in, you can look here for comparison for JAX-RS implementations.
P.S.: You should also know that Spring does not compliant to JAX-RS API, rather they have got their own API.

Why different DatagramSocket constructors behave so different? (BindException)

I'm building a program that will connect every computer in my LAN to my computer, through DatagramSocket's and DatagramPacket's (in other words, I'll be the server and the others will be clients). I made some research and read the documentation, and found out how it worked, and I've actually been able to send and recieve data across the network. I had two options for the data sending method in the client class, which I thought were equivalent, but it seems not.
The first one (Client1):
DatagramSocket socket = null;
DatagramPacket packet = null;
try
{
byte[] data= "test".getBytes();
packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.0.26"), 325);
socket = new DatagramSocket();
socket.send(packet);
}
catch (Exception ex)
{
...
}
And the second one (Client2):
DatagramSocket socket = null;
DatagramPacket packet = null;
try
{
byte[] data= "test".getBytes();
packet = new DatagramPacket(data, data.length);
socket = new DatagramSocket(325, InetAddress.getByName("192.168.0.26"));
socket.send(packet);
}
catch (Exception ex)
{
...
}
These two options came when I was making tests sending data to and from my own PC. My IP address is 192.168.0.26. With the first one I had no problems, but the second one throws two kinds of exceptions. I can verify that Client1 works running the next code in the computer at the same time
(Server)
byte data[] = null;
try
{
data= new byte[1000];
socket = new DatagramSocket(325);
packet = new DatagramPacket(datos, datos.length);
socket.receive(packet);
System.out.println(datos);
}
catch (Exception ex)
{
...
}
If I run Server first and then the Client1 option, it actually recieves the data. When I run the Client1 first and then the Server, obviously don't get any data but neither get any exceptions. The real problem (and actual question, sorry about so many, perhaps useless, info) is with Client2. If this is ran before Server, I get NullPointerException:
java.lang.NullPointerException: null address || null buffer
at java.net.DualStackPlainDatagramSocketImpl.send(DualStackPlainDatagramSocketImpl.java:115)
at java.net.DatagramSocket.send(DatagramSocket.java:676)
generated when method send() is invoked. I know maybe I should ignore this; even thought I'm a little bit newbie with Socket's, it seems wrong to send data if you know nobody will recieve it. In the other hand, when Server runs first and then Client2, I get BindException:
java.net.BindException: Address already in use: Cannot bind
at java.net.DualStackPlainDatagramSocketImpl.socketBind(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.bind0(DualStackPlainDatagramSocketImpl.java:65)
at java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:95)
at java.net.DatagramSocket.bind(DatagramSocket.java:376)
at java.net.DatagramSocket.<init>(DatagramSocket.java:231)
at java.net.DatagramSocket.<init>(DatagramSocket.java:284)
from the line when the socket is initialized.
Due to that Client1 works, I'll use it; but I'd really like to know why does it work but Client2 doesn't. I read in another forum here about that BindException, and I understood it was caused when you attempt to use one port which is already in use, but in this sense Client1 should fail too. Could someone explain me the difference between Client1 and Client2?
You are binding to the same port, if you are running it on the same machine/address, you need to bind to different ports.
Like on the server:
socket = new DatagramSocket(325); //server binds its UDP/IP socket to port 325
On the client 2:
socket = new DatagramSocket(325, InetAddress.getByName("192.168.0.26"));
you are binding to the same port on the same machine/address that the "server" is using
On client 1:
packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.0.26"), 325);
//you are specifying the destination address and port the packet should be sent.
socket = new DatagramSocket();
//but in the DatagramSocket contructor you don't pass any address or port to bind to, so it will use an available port, not 325 as it is in use by the server.
As you said you are newly to network communication, be in mind that this is UDP/IP sockets, there's TCP/IP and others. UDP/IP is not connection oriented by specification, and does not guarantee the packet to be delivered.

Reliable TCP/IP in Java

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.

Categories

Resources