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.
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
I'm writing a ServerSocket in java. I want to send some special content to client connecting to me through telnet. I want to send other content if he/she connects through Browser and etc. Is there any way to find out that user is connecting to me with telnet?
My code :
public void handleConnection(Socket socket) throws IOException {
String author = "Ehsan Akbari";
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
if(checkoutClientType(socket)=="telnet")
out.println("You are connecting through telnet :\)");
else
out.println("You are not connecting through telnet :|");
}
What should be the definition of checkoutClientType(Socket s);?
You cannot tell what program is on the other side of a socket by examining the socket itself. There is no test or operation you can perform on the socket that will distinguish the client program.
The only hope is to examine the data being transmitted to see if it matches an expected pattern, but for that you have to have some data transmitted. It might be possible to tell if the remote is telnet if you were to send a Telnet Protocol command such as AYT (Are You There), but that would probably not sit well with a different client such as a browser.
If you were able to proxy the data between the client and a handling process or thread and examine it you might be able to eventually determine if it was Telnet, but probably not, and probably not immediately.
I am writing simple Server through TCP/IP for my android app.
I am facing a problem where server only receives messages after the timeout on the app.
My server side:
System.out.println("Connection accepted");
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
capitalizedSentence = "READY";
writeToUser(outToClient, "READY".getBytes());
String response = readFromUser(connectionSocket);
// Server hangs on readFromUser();
if(response.contains("IL"))
{
byte[] bytes = DatatypeConverter.parseHexBinary(foo);
writeToUser(outToClient, bytes);
}
App side:
if (ack.equals("READY")) {
ack = "";
dataOutputStream.writeBytes(command);
dataOutputStream.flush();
buf = new byte[556];
dataInputStream.read(buf);
// app hangs on read() and gets timeout
}
The problem is that, server receives command only after application gets read timeout.
My current scenario is this:
Connection accepted: Application receives "READY"
Application sends commands and tries to read response from server
Server is hanging on readFromUser() and only receives message after the app gets read timeout.
Any ideas what am I doing wrong ?
Update:
The code works if I use readLine, instead of read(buf) ( if I understand clearly server hangs on read(buf) and is in waiting mode as socket is not closed yet even though no more data is beeing sent. )
However such way I have to add "\n" after each command, and server is only emulator, app works with different device who does not understand "\n" at the end and will crash.
Is there any way I could make this work without using readLine() ?
Update 2
public void writeToUser(DataOutputStream outToClient, byte[] bytes) throws IOException
{
outToClient.write(bytes);
outToClient.flush();
String s = new String(bytes);
writeLog("Sent to client: " + s);
}
public String readFromUser(Socket socket) throws IOException, InterruptedException
{
writeLog("Reading...");
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String clientSentence = inFromClient.readLine();
writeLog("Received: " + clientSentence);
return clientSentence;
}
Above readFromUser() method works just as expected. But, this requires adding "\n" on each command sent from client app. And real device I have to communicate with does not understand "\n" and will treat the command as unrecognized... I am writing this server simply for testing purposes and I want it to be as close to real one as possible.
Previously I was just trying to get it done without "\n" on each command using inFromClient.read(cbuf); instead of readLine() and server always got hung on read, and received command only after socket was closed on client side. Even though I know that client sent the command and is waiting for response.
The question is how can I receive command without using readLine(); and "\n" on client side.
'how can I receive command without using readLine(); and "\n" on client side'. If you do not, or can not, want to use "\n" as a command terminator, then you must use another protocol to identify the start and end of the 'command' within the TCP octet/byte stream.
What protocol does your 'real device' server use to identify the start and end of commands? If it uses a byte-by-byte state-machine to identify a valid command then you are going to have to duplicate that in your test server.
You're reading lines but you aren't writing lines. So readLine() blocks until a line terminator arrives or the peer closes the connection.
Append a \n.
Why not you increase timeout from APPs side. Or you can write a thread that will hit server in some interval for some time and if no response then show time out. This problem is in Apps side.
I am fist connecting through vpn client then I am able to do telnet and also able to get response when i paste request string on terminal.
Same request if I am trying through java program, I am not getting any response.
I can see using netstat there is established TCP connection when i try through java.
TCP 10.2.2.22:1154 184.23.23.61:7565 ESTABLISHED
Here is the java client code which sends the request.
Socket client = new Socket(serverIp, port);
OutputStream out = client.getOutputStream();
InputStream in = client.getInputStream();
String test = "TUE231363**";
StringBuffer response = new StringBuffer("response : ");
out.write(test.getBytes());
out.flush();
int c;
System.out.println("waiting for response.......>>>>>>>>>>>>>");
while ((c = in.read()) != -1) {
if (isEndOfResponse(c))
break;
System.out.print((char) c);
response.append(c);
}
client.close();
System.out.println(response.toString());
every time after few minutes [5-6 min] it exits without any response.
I am bit new to networking, can anyone suggest what I am missing.
I assume that you are telnetting to the same IP address and port that you are trying to connect to from Java.
The fact that telnet connects, and your client also appears to connect would imply that the server is running, and that it has created an bound a ServerSocket on the right IP / host. It is probably even calling accept properly. But is seems like the server is either not reading the request at all, or it is failing to send a response.
Either way, the problem is most likely on the server side ... and there's not much we can say without seeing the server-side code.
I have written a client side java application which communicates through http to a php server. I need to implement a listener on the java (client) side to respond to requests made by the php server. Currently, the java apps are hitting a text file on the server that is updated every minute.
This has worked ok, but now the number of client java apps is rising and this primitive system is starting to break down.
What is the best way to change this? I tried a java ServerSocket listener on the java client app, but can't get that to work. I am having trouble completing the communication. All examples on the web use localhost as ip address example, and my php server is remote hosted.
Do I need to get the ip address of the client machine and send that to the php server so php will know where to send the message? Here is the java code... This is all over the web...
public class MyJavaServer
{
public static void main(String[] args)
{
int port = 4444;
ServerSocket listenSock = null; //the listening server socket
Socket sock = null; //the socket that will actually be used for communication
try
{
System.out.println("listen");
listenSock = new ServerSocket(port);
while (true)
{
sock = listenSock.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
String line = "";
while ((line = br.readLine()) != null)
{
bw.write("PHP said: " + line + "\n");
bw.flush();
}
//Closing streams and the current socket (not the listening socket!)
bw.close();
br.close();
sock.close();
}
}
catch (IOException ex)
{
System.out.println(ex);
}
}
}
... and here is the php
$PORT = 4444; //the port on which we are connecting to the "remote" machine
$HOST = "ip address(not sure here)"; //the ip of the remote machine(of the client java app's computer???
$sock = socket_create(AF_INET, SOCK_STREAM, 0)
or die("error: could not create socket\n");
$succ = socket_connect($sock, $HOST, $PORT)
or die("error: could not connect to host\n");
$text = "Hello, Java!\n"; //the text we want to send to the server
socket_write($sock, $text . "\n", strlen($text) + 1)
or die("error: failed to write to socket\n");
$reply = socket_read($sock, 10000, PHP_NORMAL_READ)
or die("error: failed to read from socket\n");
echo $reply;
This simply does not work. The java app listens, but the php script never connects.
Also, is this the best method for my needs??
Thanks.
The code you include works if the php server machine could connect to the java client machine. In your case that this is all over the web, it means that the java client machine should have an IP that are accessible to public. Once you have it, assign that IP to $HOST, then the code will runs fine.
Assuming that no client can have a public IP, I think the best method is to make your java client talk to your PHP Server in request-reply manner using HTTP request. The java client, acting like a web browser, send a HTTP request and receive HTTP reply that contains data needed by your java client. And when the client numbers rise to a level that you PHP server cannot handle, you could scale it up. Although I haven't had the experience myself, scaling up a PHP server is not uncommon these days.