简体   繁体   中英

Is it possible use the Socket API from Java with a Spring-Boot web application?

When I google this subject, all I found is websockets-related stuff. I want use the Socket API from Java to send and receive data between a client and a server (the server is always a spring-boot web application, the client could be or not).

I designed the server application to run on port 4444 when I execute java -jar server.war and the client to run on port 3333 when I execute java -jar client.war . The server should listen on port 5555.

What I have so far, for the server:

controller

@Controller
public class Home {
  ServerSocket s;

  Integer PORT = 5555;

  @RequestMapping("/")
  public String index() {
    return "index";
  }

  @RequestMapping("/open_connection")
  @ResponseBody
  public void open_connection() throws Exception {
    s = new ServerSocket(PORT);
  }

  @RequestMapping("/close_connection")
  @ResponseBody
  public void close_connection() throws Exception {
    s.close();
  }

  @RequestMapping("/listen_connection")
  @ResponseBody
  public String listen_connection() throws Exception {
    Socket socket = s.accept();
    DataInputStream dis=new DataInputStream(socket.getInputStream());
    String  str = (String) dis.readUTF();
    socket.close();
    return str;
  }
}

the methods are called through this javascript code:

var isOpen = false;

function open_connection(e) {
  var url = e.dataset.url;
  var oReq = new XMLHttpRequest();

  oReq.onload = function(ev) {
    var responseText = oReq.response;
    isOpen = true;
    document.querySelector('.btn-success').style.display = 'none';
    document.querySelector('.btn-danger').style.display = 'block';
  }

  oReq.open("GET", url);
  oReq.send();
}

function close_connection(e) {
  var url = e.dataset.url;
  var oReq = new XMLHttpRequest();

  oReq.onload = function(ev) {
    var responseText = oReq.response;
    isOpen = false;
    document.querySelector('.btn-danger').style.display = 'none';
    document.querySelector('.btn-success').style.display = 'block';
  }

  oReq.open("GET", url);
  oReq.send();
}

function listen_connection(e) {
  var url = document.querySelector('.container').dataset.url;

  if(isOpen) {
    while(true) {
      var oReq = new XMLHttpRequest();

      oReq.onload = function(ev) {
        var responseText = oReq.response;
        if(responseText === 'quit') {
          break;
        } else {
          var item = document.createElement('li');
          item.setAttribute('class', 'list-group-item');
          item.innerText = responseText
          document.querySelector('.list-group').addChild(item);
        }
      }

      oReq.open("GET", url);
      oReq.send();
    }
  }
}

When I call this methods from the html view, open connection and close connection give me no erros. I have no idea how start to listen the connection to receive data from clients (I try call listen_connection from open_connection, but this way I crash the browser when I call the open connection method).

In the client, I have this:

controller

@Controller
public class Home {
  String HOST = "localhost";

  Integer PORT = 5555;

  @RequestMapping("/")
  public String index() {
    return "index";
  }

  @RequestMapping(value="/send_data", method=RequestMethod.POST)
  @ResponseBody
  public void send_data(@RequestParam("data") String data) throws Exception {
    Socket socket = new Socket(HOST, PORT);
    DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
    dout.writeUTF(data);
    dout.flush();
    dout.close();
    socket.close();
  }
}

this methods are called through this javascript code:

function send(e) {
  var url = e.dataset.url;
  var oReq = new XMLHttpRequest();

  oReq.onload = function(ev) {
    var responseText = oReq.response;
    document.querySelector('.form-control').value = '';

  }

  oReq.open("POST", url);
  var formData = new FormData();
  formData.append("data", document.querySelector('.form-control').value)
  oReq.send(formData);
}

the issue here is that when I click to call this method, I got a error 403 (forbidden).

Anyone can tell me what I am doing wrong here?

The goto would be to use SpringIntegration , TCP & UDP documentation can be found here . But in summary you can use integration flows to transform messages/communication from one form to another, and implement a bunch of standard enterprise integration patterns.

Spring boot application after all is just a java application that usually exposes some Http Interface, but not always (think about some application that gets its input from, say, messaging system).

So technically there is nothing that can prevent you from using plain sockets.

So you can create (probably of scope Singleton so that there will be only one bean like this in the application context). This bean during the initialization would open up a server socket and accept connections.

Since spring boot manages the lifecycle of the application, you can even close gracefully the server socket when the application goes down.

All this will work as long the server socket port is available and you implement the communication protocol by yourself. This the basis. Keep in mind that this way of communication is extremely low-level, so you won't have monitoring, will have to deal with thread pooling (what if there are too many requests on server running in parallel), etc.

Spring Integration or frameworks like Camel can probably wrap it all in a way that you'll be able to actually use that in production, but I think its kind of beyond the scope of the question.

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