0

I have a Java printing application, it prints ticket to a network printer using raw TCP sockets. This application is a REST listener, when it receive a command, it prints using one single connection to a single ethernet thermal printer.

This is my code used by a singleton service:

public class TcpPrinterWrapper implements PrinterWrapper {

    private static Logger log = LoggerFactory.getLogger(TcpPrinterWrapper.class);

    private PrinterOpzioni opzioni;
    private TcpWrapper wrapper;


    public TcpPrinterWrapper(PrinterOpzioni opzioni) {
        super();
        this.opzioni = opzioni;
        wrapper=new TcpWrapper();
    }



    @Override
    protected void finalize() throws Throwable {
        if(wrapper!=null) try{wrapper.close();}catch (Exception e) {}
        super.finalize();
    }


    private void openPort(){
        try {
            if(wrapper==null)
                wrapper=new TcpWrapper();
            wrapper.openPort(opzioni, opzioni.getTcpTimeout());
        } catch (Exception e) {
            log.error("Errore apertura porta",e);
            throw new HardwareException("Porta stampante non valida o non disponibile");
        }
    }

    @Override
    public synchronized void print(byte[] content, boolean close) throws Exception {
        try{
            if(wrapper==null || !wrapper.isOpened()){
                openPort();
            }
            wrapper.write(content);
            if(close)
                close();
        }catch(Exception e){
            try{
                wrapper.close();
            }catch(Exception e1){}
            throw e;
        }
    }

    @Override
    public void close(){
        try {
            wrapper.close();
            wrapper=null;
        } catch (Exception e) {}
    }

}

My question is: should it close its socket at the end of each print job? Or can a TCP socket stay opened for many hours waiting for jobs?

I don't know REST requests frequency, but I'm sure they can wait many hours but the also be called many in a minute. This is why I cannot answer, can a socket stay opened waiting for so long? In other hand can I open/close/open/close many sockets in few minutes? Should I complicate with a disconnection timer?

Am_I_Helpful
  • 18,735
  • 7
  • 49
  • 73
Tobia
  • 9,165
  • 28
  • 114
  • 219
  • *Should it close its socket at the end of each print job?* - Are there multiple socket connections being made, OR, is it just a single connection which keeps on supplying print jobs? – Am_I_Helpful Jan 23 '18 at 18:49
  • Now I have one single connection, but I cannot say if I should close it after each print job or only if I close the process. – Tobia Jan 23 '18 at 18:51
  • 1
    Could the downvoter please give a justification? – Thomas Jan 23 '18 at 18:51
  • @Tobia - It is still unclear to me. If you've only single connection, then how can you close it without affecting the process? Would you please clarify a bit more on what do you mean by **a process** (in your context)? – Am_I_Helpful Jan 23 '18 at 18:53
  • @Am_I_Helpful I rewrite the question, please let me know if now it is clear. Thanks – Tobia Jan 23 '18 at 19:02
  • I think you intended to make this a print server. If that is the case then you must keep the port open. Also, I do not see anywhere where you `accept` incoming connections. Unless I'm just not understanding your code. – jiveturkey Jan 23 '18 at 19:16
  • Consider that my code works, my question is more theoretical about sockets. Incoming connections are managed by a Spring controller, and then TcpPrinterWrapper.print() is called. I can call this method with close=true parameter for each print or not. – Tobia Jan 23 '18 at 19:20
  • Close it. Why bother trying to keep it open? – President James K. Polk Jan 23 '18 at 22:24

2 Answers2

1

You're not using raw Sockets (it is not possible using existing Java's network standard package; you'll need to use native calls with the help of JNI for utilising raw Sockets).

What you're using in your code seems to be a PrintServer having TCPSocket extending from the Java's Standard Package's TCP Socket. And, there's too much of code which has not been shared.

My question is: should it close its socket at the end of each print job? Or can a TCP socket stay opened for many hours waiting for jobs?

Ideally, each application should have process timeout, or release the resource after a certain period of time. It is the general principle of security (and best practices) to close sessions in case of request-waiting situations. By process, I mean the underlying resource if not being used should close the connection or/and give a timeout (depending on the application's use-case).

So, yes, if the class TcpWrapper extends the class Socket, you should set the connect timeout as well as the read timeout. The most important thing is: "Once the operation is done, you should close the Socket at both the client and the Server end".

You can utilise Socket pools to manage multiple connections for your print application as mentioned in the post Manage Client Socket Pool.

Am_I_Helpful
  • 18,735
  • 7
  • 49
  • 73
  • Thank you for your answer, I wrote "raw sockets" to explain that the connection with the printer is not share-printer job but a socket connection sending bytes to printer. For example I can print using putty client with "raw" connection. Obviously I'm using Tcp wrappers of Java libraries. – Tobia Jan 24 '18 at 07:54
  • @Tobia - Do you've any question left in your mind regarding this? If something is unclear, I'd like to further clarify. – Am_I_Helpful Jan 24 '18 at 07:57
  • I decided to close it after each job. Maybe there will be some overhead to reopen in case od two subsequent print, but the connection can be broken between long breaks. Thanks – Tobia Jan 24 '18 at 08:05
  • @Tobia - Don't worry much about the overheads, and please check the client-socket pool libraries which I've linked to in this answer. It is always a recommended practice to keep a timeout, and release the resources at that time to manage them efficiently. Mark my words, and it'll keep your applications better. Good Luck, :) – Am_I_Helpful Jan 24 '18 at 10:39
1

It also depends on the printer. Will it print each and every character it receives? Will it accumulate lines print them when it has received a complete line? Or does it wait for the complete page? Or for the complete job? In that case, depending on the printer protocol, you may have to close the socket for the printer to realize that this is the end of the print job.

Another aspect: in many enterprise environments firewalls cut off sockets that are inactive for certain (configurable) periods. In this case you are better off closing the socket at the end of the job.

Last, the finalize is pretty useless. Look it up.

Jonathan Rosenne
  • 2,159
  • 17
  • 27
  • The printer waits for its end command, in this case is a ZPL printer, but I can left open the connection, connection closing is not needed to print. Good clarification about firewall, this is not the case, but I should have considered it. – Tobia Jan 24 '18 at 08:08
  • You better not write your application to be dependent on a particular printer type. These things change. – Jonathan Rosenne Jan 24 '18 at 08:29