How to read response from remote server using Java Sockets - java

Part of a Java program I'm creating needs to talk to a service on a remote machine. That remote machine is running a service (written in Delphi I believe) on a Windows platform.
I need to connect to that machine, send command strings and receive (String) responses.
If I connect using Linux CLI telnet session I get responses as expected:
[dafoot#bigfoot ~]$ telnet [host IP] [host port]
Trying [host IP]...
Connected to [host IP].
Escape character is '^]'.
Welcome to MidWare server
ping
200 OK
ProcessDownload 4
200 OK
In the above the lines 'ping' and 'ProcessDownload 4' are me typing in the terminal, other lines are responses from remote system.
I created a Main in my Java class that will do the work to call the appropriate methods to try and test this (I've left out irrelevant stuff):
public class DownloadService {
Socket _socket = null; // socket representing connecton to remote machine
PrintWriter _send = null; // write to this to send data to remote server
BufferedReader _receive = null; // response from remote server will end up here
public DownloadServiceImpl() {
this.init();
}
public void init() {
int remoteSocketNumber = 1234;
try {
_socket = new Socket("1.2.3.4", remoteSocketNumber);
} catch (IOException e) {
e.printStackTrace();
}
if(_socket !=null) {
try {
_send = new PrintWriter(_socket.getOutputStream(), true);
_receive = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public boolean reprocessDownload(int downloadId) {
String response = null;
this.sendCommandToProcessingEngine("Logon", null);
this.sendCommandToProcessingEngine("ping", null);
this.sendCommandToProcessingEngine("ProcessDownload", Integer.toString(downloadId));
try {
_socket.close();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private String sendCommandToProcessingEngine(String command, String param) {
String response = null;
if(!_socket.isConnected()) {
this.init();
}
System.out.println("send '"+command+"("+param+")'");
_send.write(command+" "+param);
try {
response = _receive.readLine();
System.out.println(command+"("+param+"):"+response);
return response;
} catch (IOException e2) {
e2.printStackTrace();
}
return response;
}
public static void main(String[] args) {
DownloadServiceImpl service = new DownloadServiceImpl();
service.reprocessDownload(0);
}
}
As you will see in the code, there are a couple of sys.outs to indicate when the program is attempting to send/receive data.
The output generated:
send 'Logon(null)'
Logon(null):Welcome to MidWare server
send 'ping(null)'
So Java is connecting to the server ok to get the "Welcome to Midware" message back, but when I try to send a command ('ping') I don't get a response.
So the questions:
- does the Java look about right?
- could problem be related to character encoding (Java -> windows)?

You need to flush the output stream:
_send.write(command+" "+param+"\n"); // Don't forget new line here!
_send.flush();
or, since you create a auto-flushing PrintWriter:
_send.println(command+" "+param);
The latter has the disadvantage that the line end can be \n or \r\n, depending on the system on which your Java VM runs. So I prefer the first solution.

Related

FileWriter closes websocket connection?

I am new to server programming and websockets and I've learnt a little bit of Java 8 this year. In school we had a project where a client webpage opens your webcam, takes a photo of a barcode and then shows a photo and the nutritional value of said product. You can also just send a raw barcode number and that is what is done in this example
My side of the project was to implement a java websocket server (the backend) using the glassfish tyrus library, then receiving the number of the barcode in string format and making a request to openfoodfacts.org using their api. Finally I parsed the json file and sent it back as string format so the client app can read the string and show the correct information (product name, image url, etc)
My code is organized into two files, Serveur.java establishes a websocket server for the client to connect to and ProduitApi.java gets the information from openfoodfacts.org with the given barcode from the client.
public class Serveur {
#javax.websocket.server.ServerEndpoint(value = "/websocket")
public static class EndPoint {
#javax.websocket.OnClose
public void onClose(javax.websocket.Session session, javax.websocket.CloseReason close_reason) {
System.out.println("onClose: " + close_reason.getReasonPhrase());
}
#javax.websocket.OnError
public void onError(javax.websocket.Session session, Throwable throwable) {
System.out.println("onError: " + throwable.getMessage());
}
#javax.websocket.OnMessage
public void onMessage(javax.websocket.Session session, String message) {
System.out.println("Message from client: " + message);
//Creation du produit avec le message du client
try {
ProduitApi produit = new ProduitApi(message);
session.getBasicRemote().sendText(produit.print());
} catch (Exception e) {
e.printStackTrace();
}
}
#javax.websocket.OnOpen
public void onOpen(javax.websocket.Session session, javax.websocket.EndpointConfig ec) throws java.io.IOException {
System.out.println("OnOpen... " + ec.getUserProperties().get("Author"));
session.getBasicRemote().sendText("{\"Handshaking\": \"Yes\"}");
}
}
public static void main(String[] args) {
Server server;
server = new Server ("localhost", 8025, "/BetterFood", null, EndPoint.class);
try {
server.start();
System.out.println("--- server is running");
System.out.println(java.nio.file.FileSystems.getDefault().getPath("client") );
System.out.print("Please press a key to stop the server.");
java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
reader.readLine();
} catch (Exception e) {
e.printStackTrace();
} finally {
server.stop();
}
}
}
as you can see, when I receive the 'barcode' message, onMessage() gets called. There I instantiate an object of class ProduitApi to use the barcode to then return the information
This is my ProduitApi file without some unnecessary details
package com.gabi.serveur;
/**
*
* #author gabriel
*/
[imports]
public class ProduitApi {
private java.lang.String barcode;
final private java.net.URL url;
private java.net.URLConnection connection;
JsonObjectBuilder constructeur_objet = Json.createObjectBuilder();
String string_json;
ProduitApi(java.lang.String barcode)throws MalformedURLException, IOException {
this.barcode = barcode;
this.url = new java.net.URL("http://world.openfoodfacts.org/api/v0/product/" + this.barcode + ".json");
connection = url.openConnection();
stream();
}
public void stream() throws IOException{
if (connection != null) {
java.io.InputStreamReader response = new java.io.InputStreamReader(connection.getInputStream());
javax.json.stream.JsonParser parser=javax.json.Json.createParser(response);
while (parser.hasNext()) {
[parsing inputStream into JsonObject]
}
public String print()throws IOException{
string_json = constructeur_objet.build().toString();
System.out.print(string_json);
//FileWriter file = new FileWriter("serveur/src/main/java/com/gabi/serveur/json/final.json");
//file.write(string_json);
//file.close();
return string_json;
}
}
My problem comes from the last function ProduitApi.print() , it is supposed to return the parsed json in string form so I can send it via the sendText() as well as printing the result into my console so I can see if everything went right. As you can see there are somme commented lines; The FileWriter object that I had created was used with the purpose of writing said string to a file in my pc and let me check inside.
HOWEVER
and here is what I don't understand, If I uncomment those lines so that the print function can also write the file to my drive, The Connection Closes and then Opens again
It can be seen in the console where after printing the json string, it prints OnClose, followed by OnOpen Signaling the connection was reset for some reason.
If I remove the FileWriter section, the connection works normally, the client's connection stays open and he can make another request
End of Console Message after request:
...cuits x22 biscuits fourrés - 304g","qte":"304 g","img":"https://images.openfoodfacts.org/images/products/800/050/031/0427/front_fr.177.400.jpg"}onClose: OnOpen... null...
Finally, my question is just why writing to a file makes my program behave this way (resetting the connection). Does it have anything to do with how streams work?
I accidentally commented the filewriter portion when another Ide said it didn't find the file because I had opened the project from a different directory.

Java - CopyStreamException due to SSLProtocolException when storing file's contents in FTP server

I'm facing an issue when trying to store a file in an FTP server. When trying to upload a file to the FTP server, the file is created but its contents are not copied.
Context
We use the following configuration to access the FTP server using lftp. I cannot change this configuration, and don't know why do we use FTPS with verify-certificates disabled.
# FTPS_OPTIONS:
set ssl:verify-certificate/testhostname no;
set ftp:ssl-protect-data yes;
set ftp:passive-mode on;
I need to store certain files from a Java application. I'm using apache-commons library. The implemented code looks like this:
#Autowired
public FtpService() {
ftpsClient = new FTPSClient();
ftpsClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
}
public void uploadFile(String ftpHost, File tempFile, String destination, String filename)
throws UploadException {
ftpsClient.connect(ftpHost, 990);
ftpsClient.execPBSZ(0);
ftpsClient.execPROT("P");
ftpsClient.enterLocalPassiveMode();
ftpsClient.setKeepAlive(true);
ftpsClient.setControlKeepAliveTimeout(3000);
if(ftpsClient.login("user", "password")) {
try (InputStream fileStream = new FileInputStream(tempFile)) {
if (!ftpsClient.changeWorkingDirectory(destination)) {
throwUploadException("Destination directory not available in FTP server");
}
boolean saved = ftpsClient.storeFile(filename, fileStream);
// Following code is not executed since the exception is thrown in the previous line
if (!saved) {
throwUploadException("Unable to save file in FTP server");
}
log.info("Saved FTP file: {}/{}", destination, filename);
}
catch (UploadException | IOException e)
{
throwUploadException(e.getMessage());
}
finally
{
ftpsClient.disconnect();
if (!tempFile.delete()) {
log.warn("Unable to delete '{}' file", tempFile.getAbsolutePath());
}
}
}
}
Problem
I started with a FTPClient (non FTPSClient) but this way I wasn't able to login.
Currently (FTPSClient), I can:
change the working directory
create directories in the FTP server
I cannot:
storeFile: this method throws the following exception, and creates the file in the FTP server, but this is empty
org.apache.commons.net.io.CopyStreamException: IOException caught while copying.
Cause: javax.net.ssl.SSLProtocolException: Software caused connection abort: socket write error
listFiles()/listDirectories(): when executing this command, the obtained list is always empty. The logged user has all the required permissions in the whole FTP server
Following is the FTP's log (note that I have translated the commands to English between parenthesis), corresponding to the code shown before, that raises the exception mentioned before:
er: testhostname:990
USER *******
331 Usuario testuser OK. Clave requerida ( = User testuser OK. Password required)
PASS *******
230 OK. El directorio restringido actual es / ( = OK. The current restricted directory is /)
CWD /test/upload
250 OK. El directorio actual es /test/upload ( = Ok. The current directory is /test/upload)
PASV
227 Entering Passive Mode (<numbers...>)
[Replacing PASV mode reply address <ip_address> with testhostname]
STOR dummyfile.txt
150 Conexi├│n de datos aceptada ( = Data connection accepted)
If there is anything else I can include to improve the description, please let me know. Thanks for your help!
I had a similar problem from python connecting to an FTPS server. The error was that the server required the data channel session to be the same as the control channel session(reuse the session). The solution was to override one of the methods to do that.
You can test extending FTPClient.java and overriding the next method:
#Override
protected void _prepareDataSocket_(final Socket socket) {
if(preferences.getBoolean("ftp.tls.session.requirereuse")) {
if(socket instanceof SSLSocket) {
// Control socket is SSL
final SSLSession session = ((SSLSocket) _socket_).getSession();
if(session.isValid()) {
final SSLSessionContext context = session.getSessionContext();
context.setSessionCacheSize(preferences.getInteger("ftp.ssl.session.cache.size"));
try {
final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
sessionHostPortCache.setAccessible(true);
final Object cache = sessionHostPortCache.get(context);
final Method putMethod = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
putMethod.setAccessible(true);
Method getHostMethod;
try {
getHostMethod = socket.getClass().getMethod("getPeerHost");
}
catch(NoSuchMethodException e) {
// Running in IKVM
getHostMethod = socket.getClass().getDeclaredMethod("getHost");
}
getHostMethod.setAccessible(true);
Object peerHost = getHostMethod.invoke(socket);
putMethod.invoke(cache, String.format("%s:%s", peerHost, socket.getPort()).toLowerCase(Locale.ROOT), session);
}
catch(NoSuchFieldException e) {
// Not running in expected JRE
log.warn("No field sessionHostPortCache in SSLSessionContext", e);
}
catch(Exception e) {
// Not running in expected JRE
log.warn(e.getMessage());
}
}
else {
log.warn(String.format("SSL session %s for socket %s is not rejoinable", session, socket));
}
}
}
}
I found this Java solution here: https://stackoverflow.com/a/32404418/19599290

Calling Perl script from Java (JAX-WS in Eclipse)

I have a JAX-WS webservice that receives a string as parameter, calls a Perl script, and returns the string converted to upper case. It is running on Tomcat 8 (localhost on Eclipse).
When I type from the console:
curl -X POST --data "mystring=HelloWorld" http://localhost:8080/MyServices/api/generatePath
Everything works except for the Perl call. On the debugger I see that line is executed, but apparently nothing happens (not even errors). If I run perl /home/me/workspace/match.pl from the console it works perfectly. The path of the match.pl file is correct.
In addition, process.exitValue() return 2.
#Path("/")
public class MyServices {
#POST
#Path("/generatePath")
#Produces(MediaType.APPLICATION_JSON)
public Response generatePathService(
#FormParam("mystring") String myString) {
Process process = null;
try {
process = Runtime.getRuntime().exec("perl /home/me/workspace/match.pl --lang en");
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Response.status(200).entity(myString.toUpperCase()).build();
}
}
I got similar stuff some time ago. The solution for me was to 'accept' the output of the program. Something like this:
Process p = Runtime.getRuntime().exec(cmd);
final InputStream is = p.getInputStream();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (is.available() != 0) {
is.read();
}
} catch (IOException ex) {
}
}
}).start();
You should also try to get the error stream with p.getErrorStream(). An alternative could be to change your perl program in that way that there is nothing printed to standard out or error out.
Or you call a shell script and redirect the output to dev/null (someting like ´blabla>/dev/null`.

Pyro4 connect with java

Hi all I have question related with Pyro4 and Java. My question is how can I send information between RMI server in Java and clients RMI in Python?.
This is my code, I don't have any errors but I can't send anything.
Java Code:
implements ReceiveMessageInterface
{
int thisPort;
String thisAddress;
Registry registry; // rmi registry for lookup the remote objects.
// This method is called from the remote client by the RMI.
// This is the implementation of the �gReceiveMessageInterface�h.
public void receiveMessage(String x) throws RemoteException
{
System.out.println(x);
}
public RmiServer() throws RemoteException
{
try{
// get the address of this host.
thisAddress= (InetAddress.getLocalHost()).toString();
}
catch(Exception e){
throw new RemoteException("can't get inet address.");
}
thisPort=3232; // this port(registry�fs port)
System.out.println("this address="+thisAddress+",port="+thisPort);
try{
// create the registry and bind the name and object.
registry = LocateRegistry.createRegistry( thisPort );
registry.rebind("rmiServer", this);
}
catch(RemoteException e){
throw e;
}
}
static public void main(String args[])
{
try{
RmiServer s=new RmiServer();
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
And this is my code in Python:
import Pyro4
proxy=Pyro4.core.Proxy("PYRONAME:PhDJara/127.0.1.1")
print("5*11=%d" % proxy.multiply(5,11)) print("'x'*10=%s" %
proxy.multiply('x',10))
Thanks for your help.
jarain78
What makes you think that you should be able to connect these two?
Pyro4 is only conceptually similar to Java's RMI, but they're two totally different protocols. You cannot connect them directly.
If you want to write a Python client using Pyro and talk to a server, that server has to be a Pyro server. The only way to create one in Java is by using Jython + Pyro.

Send a String to serial port as a command for embedded device

I am working on a project that involves an embedded device. I am expected to send a command to this device. This command is a string: "LAMP1_ON\r\n";
I am using RXTX with java and sending the data via serial port. But when i send the String command, the device receives "AMP_N" and some other scattered string.
I have no idea why it is so, and how i can fix it.
My code is below:
public class SerialWriter implements Runnable {
OutputStream out;
String str;
public SerialWriter(OutputStream out, String str) {
this.out = out;
this.str = str;
}
public void run() {
try {
byte[] array = this.str.getBytes();
this.out.write(array);
this.out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I expect to send the string to the port via the write method. It works but it doesn't send the exact String that is contained in this.str instead it sends "AMP_N" and "AMP" and scattered Strings
I have seen the problem. I didn't set the FLOWCONTROL property correctly. Thank you. This code works fine
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);

Categories

Resources