Zpl printer receive fragmented data from Java application - java

Background
I am trying to create a java application to send ZPL command to a ZPL printer and get a label printed.
I set up a ZPL emulator(https://chrome.google.com/webstore/detail/zpl-printer/phoidlklenidapnijkabnfdgmadlcmjo) by following this post : Emulate ZPL printer
Issue
After setting the emulator up and add it as zpl printer via mac Printer&Scanner ,
I try to use lp command to print it. it is stable the reliable:
lp -o "raw" -q1 -d zpl <<< "^XA\n^FO50,60^A0,40^FDWorld Best Griddle^FS\n^FO60,120^BY3^BCN,60,,,,A^FD1234ABC^FS\n^FO25,25^GB380,200,2^FS\n^XZ"
However, my use case is send the command to a printer remotely on the network, Therefore I need to create a java application to send the Zpl command to the printer. It succeeds initially, then it randomly get splitted:
java code:
import java.io.*;
import java.net.*;
class TCPClient
{
public static void main (String argv[]) throws Exception
{
Socket clientSocket=new Socket("127.0.0.1",9100);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream() );
try {
outToServer.writeBytes("^XA\n^FO50,60^A0,40^FDWorld Best Griddle^FS\n^FO60,120^BY3^BCN,60,,,,A^FD1234ABC^FS\n^FO25,25^GB380,200,2^FS\n^XZ");
} catch (Throwable e) {
System.out.println(e);
}
outToServer.flush();
outToServer.close();
clientSocket.close();
// outToServer.flush();
}
}
Result:
So quite often, it succeeds once and then following 2 or 3 printing get fragmented or failed. I suspect it might be the socket TCP fragmentation issue. or there any socket option I can configure? But not sure how to solve it. Can anyone help here?
Update:
I try to use wireshark. The issue resides in the TCP package size:
For lp command, everything is sent as one single pack:
As for java app, it is broken down into smaller packs for some reason.
But I still don't know how to configure the pack size. Also it confuses me a lot why Java app will break the data packet to like 1 byte or two byte sized?

I think you are using a wrong method to send printing job. I'm not sure lp command uses Socket connection. Try calling lp from Java using Runtime.getRuntime().exec:
String cmd = "lp -o \"raw\" -q1 -d zpl <<< \"^XA\n^FO50,60^A0,40^FDWorld Best Griddle^FS\n^FO60,120^BY3^BCN,60,,,,A^FD1234ABC^FS\n^FO25,25^GB380,200,2^FS\n^XZ\"";
Runtime.getRuntime().exec(String.format(cmd));

Related

Java Socket Packet Interception

I'm trying to write a socket program in Java that intercepts data/packets.
I've successfully written this in python:
import socket
def createListener(port):
srvSock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
srvSock.bind(('localhost', port))
srvSock.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
while True:
raw_data, addr = srvSock.recvfrom(65536)
print('data: ' , raw_data)
createListener(80)
This is my basic Java socket program
public static void main(String[] args) {
try{
ServerSocket ss = new ServerSocket(80);
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
String str = (String)dis.readUTF();
System.out.println("data: "+str);
ss.close();
} catch(IOException i){
System.out.println(i);
}
}
However, when run, it doesn't intercept all data moving through the port on the network like the python program does. Specifically this line srvSock.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) in the Python script enables the socket to listen to the port and capture/intercept the entirety of the data going through it.
I cannot find a Java alternative to this syntax or any solution to my problem at all for that matter.
I would appreciate any help in how to use sockets to intercept packets on a network port.
Thanks
Im fairly certain what you are trying to do cannot be done with Java. It looks like you are trying to use "promiscuous mode", but Java sockets cannot be started in promiscuous mode. Java sockets are an end-to-end implementation: they can't listen on the network port for all traffic. For sure the network port would have to be in promiscuous mode, but I don't think Java is the right choice for you.
The only thing I can think of that might get you there would be doing a native call in something like JNI, but I wouldn't even really know where to start with that.
Here is a really old post that I found that is kind of related: java socket and web programing
From the looks of it, you're trying to read incoming bytearrays as string lines.
If that is so, this is what I do to read lines without missing a single line (In Kotlin):
socket.getInputStream().bufferedReader(Charsets.UTF_8).forEachLine {
it -> { /* Do what you wanna do with the input */ }
}
In Java, it's much less abstract :
BufferedReader(InputStreamReader(socket.getInputStream(), Charsets.UTF_8), 8 * 1024)
Then, use lines from this buffered reader as a line sequence to read your incoming lines.

Special character encoding in my simple Java HTTPServer

I have a simple Java application, basically a server implemented using com.sun.net.HttpServer API, that reads a file and simply sends back the texts after some processing. The server part simply looks like this:
server = HttpServer.create(new InetSocketAddress(serverPort), 0);
logger.info("EventRetriever REST server listening to port: " + serverPort);
server.createContext("/getEvents", new MedatadaHandler());
server.setExecutor(null);
server.start();
// ...
#Override
public void handle(HttpExchange he) throws IOException {
//...
String response = requestEvents();
he.sendResponseHeaders(200, response.length());
OutputStream os = he.getResponseBody();
os.write(response.toString().getBytes());
os.close();
}
//...
public String requestEvents(){
//...
// this printing on the console looks fine though:
logger.info(jsonString);
return jsonString;
}
I run my jar file with java -jar myApp.jar on a command line or simply on my IDE. I'm witnessing some weird behaviors, sometimes just hanging, when it requires sending texts containing special characters, such as the music symbol ♪. When I call the IP:PORT/getEvent via a browser, the behavior is so weird:
If I run it on a Windows Powershell or Command Prompt, the symbol appears as ? on the console, and what I get from the browser is also shown as ?. But when I run the program on a linux server or my Eclipse IDE, it is shown correctly on the console (as ♪), but on the browser, I get the following error, although the status is 200 OK. I see on the console the java application keep looping printing the line every few seconds (as if it is trying to send the data, but can't maybe something is blocking it!). But I don't get any exception or errors on the app (I log all possible errors).
I'm very confused for this behavior. What's going on?!
First, why what I get is dependent on the environment I run my Java app?! If Windows Command Prompt/Powershell shows the character as ?, I expect it just showing it locally like that. Why should I see it also as ? on my browser?! Java app must be independent of the environment.
And second, what is going on with that error on the Linux/Eclipse envrionment when requesting a line that has this character?
The issue as could be predicted, was related to getBytes() and UTF-8 String representations. Did the following and it was all good then:
he.sendResponseHeaders(200, response.getBytes("UTF-8").length);
OutputStream os = he.getResponseBody();
os.write(response.getBytes("UTF-8"));

Invoking Seagull Diameter Client using Java

i need to send some messages from my java web application to some servers using Diameter protocol, in particular CCR-CCA scenario. I had a look at jdiameter opensource project, but my usecase does not require such complexity, since that i just need to send a single request and log the response (actually i don't even need the CER-CEA part).
So i thought i could just have used Seagull running under my webapp. I downloaded Seagull (for Windows), and what i'm trying to do is basically to run the .bat file coming from Seagull for the diameter environment from my java environment.
That's what i've done till now..
1) A simple test to invoke the client.. Here wrapper simply sets working dir and starts the process
public static void main(String[] args) {
List<String> cmd=new ArrayList<>();
cmd.add("cmd.exe");
cmd.add("/c");
cmd.add("my_start_client.bat");
JavaProcessBuilderWrapper wrapper = new JavaProcessBuilderWrapper();
Process p = wrapper.createProcess(RedirectErrorsTo.STDERR,
new HashMap<>(), new File("my_working_dir"), cmd);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder output = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
output.append(line);
}
System.out.println(line);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2) I modified the client's and server's .bat files coming from Seagull to use CCR-CCA protocol.
Running Java main with this configuration caused a
Fatal: Keyboard saved configuration failure error
on my logs.
3) So, as mentioned here i further modified my client's .bat file to run in background mode, adding -bg at the end. Now my client's bat look like this
#ECHO OFF
rem
"Diameter Start Script Sample"
"Local env"
SET RUN_DIR=C:\Program Files\Seagull
set PATH=%PATH%;%RUN_DIR%
set LD_LIBRARY_PATH=%RUN_DIR%
set RUN_DIR=%RUN_DIR%\diameter-env\run
cd %RUN_DIR%
cls
mode 81,25
echo "Seagull Diameter Client Sample Start"
seagull -conf ..\config\conf.client.xml -dico ..\config\base_ro_3gpp.xml -scen ..\scenario\ccr-cca.ro.client.xml -log ..\logs\ccr-cca.client.log -llevel ETM -bg
pause
Since i was facing some troubles, to keep things simple, i just tried to make it work at least via cmd (not using my java method), but i think background mode is messing around, because now when i start my server and then my client in bg mode, sometimes i get a
Fatal: Forking error
but the most of the times, the client send a single message and then on my console i see that my software is causing connection abort (error code -1), and from the log i see that the channel just get closed, and my client does not even receive an answer. (NB for now i left the configuration files untouched)
Has any of you faced this behaviour? Is something else closing the connection (firewall perhaps)? Do i have to provide other configurations to make this work?
Once i can get this working, can i use my java web app (with a method similar to the one i already mentioned) to make diameter calls?
Thanks in advance, any help is really welcomed.

Java app cannot communicate with RN-171 wifi module

I'm writing a Java code which have to send some data to an elecronic system and to receive some data from it through wireless. The electronic system is made of PIC32 and RN-171 module. I'm now trying to connect to the RN-171 network and to send and receive some data. Although I can in my java code set up an OutputStream and send some data to the RN-171 properly, I can't set up an InputStream and my app launches the following exception:
java.io.StreamCorruptedException: invalid stream header: 2A48454C
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:804)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299)
at TestController.sendParametersToWirelessModule(TestController.java:44)
at TestController.main(TestController.java:30)
The code in my java app, which generates the exception is:
try{
//1. creating a socket to connect to the server
requestSocket = new Socket("1.2.3.4", 2000);
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
sendMessage(message); }
(The arrow indicates the code line which generates exception)
Is there a solution? Could anyone help me please?
Thanks
Use the following code instead:
out = requestSocket.getOutputStream();
in = requestSocket.getInputStream();
ObjectOutputStream/ObjectInputStream are used to serialize/deserialize Java objects. There is also no point in flushing the output stream before writing to it.

send stringt from android over wifi and recieve in PC(java program)

I want to make simple android app in which i simply have textview, and a button. on clicking that button, string in textview is broadcast and received at PC. am new to android programming and network programming.
1. Please suggest what tool to be used in PC.
2. Some simple steps to achieve this.
3. some healthy tutorials to understand things better.
Sorry if i sound stupid :P
Thanks in advance.
Welcome to StackOverflow!
Well it sounds like you want to jump into the world of programming Android head first. That's fine but you should start somewhere. The best series of tutorials I've seen to date is at The New Boston. The videos are very easy to understand and the series is made of 200 videos. It covers everything from downloading and installing Eclipse (which is one tool you can use to develop Android apps) all the way to some pretty advanced concepts. So if you have a basic understanding you can pick and choose which videos you want to watch, if you want a full crash course just watch them all. It also has around 3000 other videos on all programming languages. Such as Java which you will need if you don't already know.
On the P.C. side if you don't have any live servers set up to play with I suggest downloading XAMPP at this link XAMPP. It allows you to create a number of things on your own computer, all of which are free. Such as a SQL database with phpmyadmin and a number of other things. All in all if you watch even a few of the 200 videos at The New Boston you will have a much better understanding of what you need to do to accomplish your goals. You will also have a better understanding of what to ask for specifically in the future. Hope this helps, if you need anything else just ask
Well, i'm not sure if this is the best way but still is a way, you could use SMB for android, and for the PC just a normal Java program so:
1: for PC you could use Java (since you use Java as a topic i supose that you know how to do a single program with this programming language
as a suggestion for achieve number 1, you could do a program that every 3-5 seconds constantly check if a empty File have data or still empty and if it has data then show a Dialog with the data, a showMessageDialog would do the job.
2: for android use what i said first, with that you could read or write a File on the PC from your android device, of course if both the PC and android device are in the same network
at this point, just write the String of the TextView or EditText in the File on the PC being checked by the java program, let me know if this help you or if you want more specific details, but i think with this you could do what you want. Sorry for my English, still learning it :)
It sounds like sockets would be good for what you want to do.Basically, you'll need to have a server script/program running on the PC and the android program can send a connection request and then a packet with the string.
You'll need to create a ServerSocket with something like this on the server and have it listen on a port of your choosing.
ServerSocket serverSocket = null;
int port = 9876;
try {
serverSocket = new ServerSocket(port);
} catch ( Exception e ) {
System.out.printf("Could not listen on port: %d", port );
System.exit(-1);
}
Often a new thread is used to accept the connection like this.
new Thread(new ServerThread(serverSocket.accept())).start();
The run() method of the ServerThread can be as simple as this
try {
Scanner socketIn = new Scanner(this.clientSocket.getInputStream());
PrintWriter socketOut = new
PrintWriter(this.clientSocket.getOutputStream(), true);
while(socketIn.hasNext() {
System.out.println(socketIn.next());
}
} catch (Exception e) {
}
You can create a socket on the client side (in your case on the android device) with code like this. (Note that android won't let you do this in your main thread so you'll have to create the connection in another thread.
public void sendRequest(final String message) {
Log.d("test", "log");
new Thread() {
#Override
public void run() {
try {
Socket socket = new Socket(InetAddress.getByName(HOST), PORT);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(message);
} catch (Exception e) {
Log.d("Exception in thread", e.getStackTrace()+"");
}
}
}.start();
}
Since you're just doing this on your wifi, instead of InetAddress.getByName(HOST), you can just put the local IP address of the PC. Also, if you are planning on this working always, rather than just learning and practicing around, it would be good to set up the PC with a static local IP on your network. There are plenty of tutorials for doing that on different OSs out there.
Fortunately, socket programming in java is pretty simple. You can use the Scanner and Printwriter to read and write to sockets.
Please note that I have not tested the above code, but the principle is sound.
Here are a few sites with some info.
http://cs.lmu.edu/~ray/notes/javanetexamples/
http://docs.oracle.com/javase/tutorial/networking/sockets/ I like this one
Edit. I could only post two of the links because my rep is low.

Categories