【问题标题】:Java and PHP socket communication and AJAXJava 和 PHP 套接字通信和 AJAX
【发布时间】:2016-03-16 18:20:31
【问题描述】:

我有一个 Java 应用程序正在检查文件系统中是否有更改 - 创建、删除和修改文件和文件夹。它正在向 PHP 应用程序发送消息。所以这是Java应用程序正在运行的情况,我正在指定目录中创建一个新文件。 Java 正在捕获它并将其显示在控制台上(用于测试目的),然后将其发送到 PHP。当我刷新时,我看到了消息,但是如果我不刷新页面并在指定的目录中创建一个新文件,Java 既不会在控制台中显示该消息,也不会将其发送到 PHP。所以似乎基本上在文件夹中的每次更改之后我都必须刷新以捕捉更改。我想知道是否可以使用 AJAX 来避免每次更改后的刷新。如果 AJAX 不是一个选项或者它不会工作,还有其他方法可以做到这一点吗?这是我的代码:

主要

package com.company;

import java.io.IOException;
import java.nio.file.*;

import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;

public class Main {

    public static final String DIRECTORY_TO_WATCH = "D:/Test";

    public static void main(String[] args) throws IOException, InterruptedException {
    // write your code here
        Path toWatch = Paths.get(DIRECTORY_TO_WATCH);
        CommunicationServer server = CommunicationServer.getInstance();
        if(toWatch == null) {
            throw new UnsupportedOperationException("Directory not found");
        }

        // make a new watch service that we can register interest in
        // directories and files with.
        WatchService myWatcher = toWatch.getFileSystem().newWatchService();
       // CommunicationServer server = new CommunicationServer();

        // start the file watcher thread below
        MyWatchQueueReader fileWatcher = new MyWatchQueueReader(myWatcher, server);
        Thread th = new Thread(fileWatcher, "FileWatcher");
        th.start();

        // register a file
        toWatch.register(myWatcher, ENTRY_CREATE, ENTRY_MODIFY);
        th.join();
    }
}

读者

package com.company;

import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

/**
 * Created by Ivan on 3/16/2016.
 */
public class MyWatchQueueReader implements Runnable {

    /** the watchService that is passed in from above */
    private WatchService myWatcher;
   private CommunicationServer server;
    public MyWatchQueueReader(WatchService myWatcher, CommunicationServer server) {
        this.myWatcher = myWatcher;
        this.server = server;
    }

    /**
     * In order to implement a file watcher, we loop forever
     * ensuring requesting to take the next item from the file
     * watchers queue.
     */
    @Override
    public void run() {
        try {
            // get the first event before looping
            WatchKey key = myWatcher.take();
            while(key != null) {
                // we have a polled event, now we traverse it and
                // receive all the states from it
                for (WatchEvent event : key.pollEvents()) {
                    System.out.printf("Received %s event for file: %s\n",
                            event.kind(), event.context() );
                    System.out.printf("Received\n");
                    String line = "Received " + event.kind() + " event for file: " + event.context() + "\n";
                    server.StartCommunicationg(line + "\n");
                    System.out.printf(" Not Received\n");
                }
                key.reset();
                key = myWatcher.take();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Stopping thread");
    }
}

服务器:

package com.company;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by Ivan on 3/16/2016.
 */
public class CommunicationServer {
    private static int port = 20222;
    private static ServerSocket listenSock = null;
    private Socket sock = null;
    private static CommunicationServer instance = null;

    protected CommunicationServer() {
        System.out.println("Communication has started");
    }

    public static CommunicationServer getInstance() {
        if (instance == null) {
            instance = new CommunicationServer();
            try{
                listenSock = new ServerSocket(port);
            } catch (IOException ex){
                ex.printStackTrace();
            }
        }

        return instance;
    }

    public void StartCommunicationg(String message) {
        try {



            //while(true) {
                this.sock = listenSock.accept();

                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));

                writer.write(message + "/n");
                writer.flush();
                writer.close();
                sock.close();
            //}
        } catch (IOException ex) {
            ex.printStackTrace();
        }


    }
}

PHP

<?php

$PORT = 20222; //the port on which we are connecting to the "remote" machine
$HOST = "localhost"; //the ip of the remote machine (in this case it's the same machine)

$sock = socket_create(AF_INET, SOCK_STREAM, 0) //Creating a TCP socket
        or die("error: could not create socket\n");

$succ = socket_connect($sock, $HOST, $PORT) //Connecting to to server using that socket
        or die("error: could not connect to host\n");

//$text = "Hello, Java!"; //the text we want to send to the server

//socket_write($sock, $text . "\n", strlen($text) + 1) //Writing the text to the socket
        //or die("error: failed to write to socket\n");

$reply = socket_read($sock, 10000, PHP_NORMAL_READ) //Reading the reply from socket
        or die("error: failed to read from socket\n");

echo $reply;
?>

整个想法是我有一个文件夹,比如说 D:\Test。不确定是否可以向用户显示是否有更改 - 仅使用 PHP 创建文件夹或文件。所以我决定用Java来寻找文件系统的变化。当发生更改时,用户应该会在浏览器中看到一条通知。如果 PHP 应用程序没有运行,Java 应用程序应该检查此文件夹中的更改,当 PHP 应用程序再次运行时,它应该会收到所有在文件夹中完成的更改..两个应用程序之间的通信存在很多问题,我想知道使用数据库是否会更好?但随之而来的问题是,PHP 将如何知道数据库已更新...这里真的很困惑...

我们将不胜感激。

问候, 伊万

【问题讨论】:

  • 那么如果你的PHP服务器没有打开socket,Java服务器不会打印FS更改到控制台?这似乎是一种非常奇怪的行为。即使没有 PHP,Java 服务器也应该继续运行并打印到控制台。除此之外,您可以使用不断向 PHP 服务器发送请求的 Ajax,也可以使用 websockets。 PHP 有 websockets(查看Ratchet)。编辑:还想提一下,IE9 或更低版本不支持 websocket。您可以将 flash polyfill 用于不支持它的旧浏览器
  • 我投票决定将此问题作为题外话结束,因为 OP 已发布“事物正在通信”的答案,但他不了解 AJAX 事物。所以它要么太宽泛,要么不能再复制,但无论如何都应该关闭。

标签: java php ajax sockets


【解决方案1】:

本质上我不同意你的CommunicationServer Java Class,最好使用Java Servlet,而不是使用socket和PHP。

如果你想使用这个策略我不得不说浏览器上加载的网页不会自动刷新,它需要你按下刷新键或者你添加一个可以在一段时间后加载的 AJAX 代码.例如,您可以使用这样的代码

setInterval(function(){
  // your code
}, 10000);

有关此范围的更多信息,我强烈建议您查看link

【讨论】:

    【解决方案2】:

    试图了解您的问题,我认为您可能需要一个额外的过程。 AJAX 可以提供帮助,但它并不能解决 PHP 需要保持旋转的问题。

    您可以只使用 AJAX 继续轮询 PHP 实例,但我认为它会错过任何可能发生在轮询时间之间的文件更改事件,因为它们似乎没有被 PHP 会话捕获。

    一种解决方案是 WebSockets,它允许您基于事件与用户通信数据,因此,您可以有一个 TCP 套接字到您的 Java 应用程序,一个 WebSocket 到最终用户,它将通过有关文件更改发生时的任何信息,但是支持是有限的,这可能很困难。

    或者,您可以让 PHP 服务器上的一个进程在后台运行,将此信息提交给各种数据库(因为它在同一台服务器上运行,Java 小程序可能会执行此操作,具体取决于您的场景),然后只需为条目添加时间戳,并让 AJAX 轮询 PHP 会话。这样,无论轮询时间多长,都不会丢失或丢弃任何内容,并且如果条目不再相关,您可以在转发条目后删除它们。

    无论哪种方式,使用网络浏览器解决此问题可能会很棘手,因为您正试图将新信息通知客户端。如果你觉得懒惰,你可以让 PHP 从不关闭会话,并继续向浏览器回显数据。

    【讨论】:

    • 我明白了...我在最初的帖子中添加了其他信息,因为我想知道使用数据库是否会更好。我在这里感到困惑,真的不确定这里最好的方法是什么......
    • @Ivan 如果您正在寻找最简单的解决方案,这样您就不必担心多线程或套接字,那么您可以只使用 PHP 映射并发送文件系统的详细信息。一个要求。它的性能不是很高,但它会为你工作,而且也很简单。然后让 AJAX 每隔 5 秒左右轮询一次会话,这将是一个“实时文件系统查看器”,无需付出太多努力。
    猜你喜欢
    • 1970-01-01
    • 2015-05-12
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 2019-02-14
    • 1970-01-01
    相关资源
    最近更新 更多