简体   繁体   中英

Simple TCP/IP socket communication using ColdFusion

I've done some searching and it doesn't seem like there is much in the way of success in establishing a tcp/ip socket connection successfully via Coldfusion. I'm trying to act as a simple client and send a string over and get a response. Adobe's EventGateway requires server-side setup, which I can't touch, but also appears to be a listener only (according to Adobe's doc, "It can send outgoing messages to existing clients, but cannot establish a link itself.").

There is another example on SO/cflib.org that is the prevailing post over the web invoking Java objects, but I'm not succeeding with it and it seems pretty much everyone else has some degree of trouble with it. In my attempts, I can get it to init/connect a socket, but nothing else. If I try to send a string, the CF page loads fine but the server side seemingly never sees anything (but will log or note a connection/disconnection). If I try to read a response, the page will never load. If I close the server while it's trying, it will show a connection reset while trying readLine(). I have tried this with an in-house app as well as a simple Java socket listener that will send a message on connect and should echo anything sent.

Is this just not a job for CF? If not, any other simple suggestions/examples from the jQuery/Ajax realm?

Java listener app:

package blah;

import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;

import java.io.*;
import java.net.*;

class SocketServer extends JFrame
    implements ActionListener {

/**
 * 
 */
private static final long serialVersionUID = 1L;
JButton button;
   JLabel label = new JLabel("Text received over socket:");
   JPanel panel;
   JTextArea textArea = new JTextArea();
   ServerSocket server = null;
   Socket client = null;
   BufferedReader in = null;
   PrintWriter out = null;
   String line;

   SocketServer(){ //Begin Constructor
     button = new JButton("Click Me");
     button.addActionListener(this);

     panel = new JPanel();
     panel.setLayout(new BorderLayout());
     panel.setBackground(Color.white);
     getContentPane().add(panel);
     panel.add("North", label);
     panel.add("Center", textArea);
     panel.add("South", button);

   } //End Constructor

  public void actionPerformed(ActionEvent event) {
     Object source = event.getSource();

     if(source == button){
         textArea.setText(line);
     }
  }

  public void listenSocket(){

    try{
      server = new ServerSocket(4444); 
    } catch (IOException e) {
     System.out.println("Could not listen on port 4444");
      System.exit(-1);
    }

    try{
      client = server.accept();
 //Show connection status in text box, and send back to client
      line = " Connected ";
      out.println(line);
      textArea.setText(line);
    } catch (IOException e) {
      System.out.println("Accept failed: 4444");
      System.exit(-1);
    }

    try{
      in = new BufferedReader(new InputStreamReader(client.getInputStream()));
      out = new PrintWriter(client.getOutputStream(), true);
    } catch (IOException e) {
      System.out.println("Accept failed: 4444");
      System.exit(-1);
    }

    while(true){
      try{
//Try to concatenate to see if line is being changed and we're just not seeing it, show in textbox
        line = line + " " + in.readLine();
        textArea.setText(line);
//Send data back to client
        out.println(line);
      } catch (IOException e) {
        System.out.println("Read failed");
        System.exit(-1);
      }
    }
  }

  protected void finalize(){
//Clean up 
     try{
        in.close();
        out.close();
        server.close();
    } catch (IOException e) {
        System.out.println("Could not close.");
        System.exit(-1);
    }
  }

  public static void main(String[] args){
        SocketServer frame = new SocketServer();
    frame.setTitle("Server Program");
        WindowListener l = new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                        System.exit(0);
                }
        };
        frame.addWindowListener(l);
        frame.pack();
        frame.setVisible(true);
    frame.listenSocket();
  }
}

CF Simple Send (minus HTML header/footer, IP to be hard-coded, port on simple listener = 4444):

<cfset sock = createObject( "java", "java.net.Socket" )>
<cfset sock.init( "ip.ip.ip.ip", 4444)>

<cfset streamOut = sock.getOutputStream()>

<cfset output = createObject("java", "java.io.PrintWriter").init(streamOut)>
<cfset streamOut.flush()>

<cfset output.println("Test Me")>
<cfset output.println()>

<cfset streamOut.flush()>

<cfset sock.shutdownOutput()>
<cfset sock.close()>

Simple CF Read (again, minus header/footer template, IP of server to be hard-coded, port 4444)

<cfset sock = createObject( "java", "java.net.Socket" )>
<cfset sock.init( "ip.ip.ip.ip", 4444)>

<cfset streamInput = sock.getInputStream()>
<cfset inputStreamReader= createObject( "java", "java.io.InputStreamReader").init(streamInput)>

<cfset input = createObject( "java", "java.io.BufferedReader").init(InputStreamReader)>

<cfset result = input.readLine()>

<cfset sock.shutdownInput()>
<cfset sock.close()>

I've tried adding some sleeps here and there and also have tried a send not using PrintWriter/using just ObjectOutputStream and writeObject() , but same behavior. Any help would be greatly appreciated. Thanks!

This is going to be a very challenging process to implement in ColdFusion, even when taking advantage of Java, for the simple reason of:

Socket communication is real-time, while web requests have finite starting and stopping points.

For example, when you make a ColdFusion template request, everything (variables, shared memory, object instantiation, etc.) lives within the context of the page request--and (barring a few caveats) dies when the page request ends. So, let's assume for the moment that you had a CFML template that performed the following tasks when requested:

  1. Opened a socket.
  2. Established a connection to a remote ip:port.
  3. Listened for a response.
  4. Printed that response to the browser.

Let's assume further that your code is up-and-running, tested, and working. You are able to open the socket, connect to a remote ip and port (you actually see the incoming request on the remote server, and can confirm this) and for all intents and purposes...your connection is good.

Then, 10 minutes after you executed your CFML page, the remote server sent a string of text over the connection...

...there is nothing on your CFML end that is alive and awaiting that response, ready to print it to the browser. The objects that you instantiated, used to open a socket, and connect...have all gone away, when the CFML template request ended.

This is why (as stated above) when you tried to "read a response", you observed that the page never loaded. What's happening is that ColdFusion is being told "stand by please, we could actually maybe possibly get some data over this socket"...so it blocks the web request from ending and waits...which manifests to the user as what appears to be a "hung" web page.

The nature of real-time socket communication is that it is connected and listening, waiting for a response...and unfortunately, a running web-page cannot run (and 'wait') forever, it will eventually timeout.

The bottom line is that while Java will allow you to open / connect / send / receive / close raw sockets, doing so from within the context of a CFML page may not be the approach you are ultimately looking for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM