如何实现B/S结构客户端与服务器端数据同步?

时间:2022-02-24 09:00:40
问题是这样的
我现在想用B/S实现一个系统,要求Browser端能够实时的从服务器端获取数据,并进行更新。
由于考虑到是实时的,随意希望能避免定时刷新的方法。
目前想到的一种方法是,在Browser端嵌入一个Appelt,通过Socket与数据库进行通讯。
但是,不知道如何去写。
请问,有没有什么类似的开源项目,或者代码实例可以参考。
另外,有没有什么更好的解决方案?
谢谢~

19 个解决方案

#1


以我多年的经验,还是定时刷新吧,通过applet的方式局限性太大,其他一般也没什么太好的方案,要不就是使用activeX还可能不错

#2


B/S结构做实时的东西不太好吧

#3


to  majy(小马哥):
由于对实时性要求比较高,所以原则上尽量不希望用定时刷新的方式。有没有什么可以参考的东西用您提到的方法实现的?当然我说的是B/S结构的

to minisun2000(天生不专一):
恩,是不太好,不过想做一个,呵呵


----------------------
另外,我还想到一些技术。但是不知道是否能够用到这个东西上来:JMX, AJAX, JMS
由于我对这些技术不是太熟悉,不知道是否适用,熟悉这些技术的朋友,或者做过类似系统的朋友欢迎您们的建议:)

#4


你只是希望不定时刷新吗,不知道xmlhttp能否满足你的要求

#5


to usaspy(行走的鱼):
您说的是AJAX吗?呵呵
那个东西,好像也是定时的进行通讯吧。
我看了https://bpcatalog.dev.java.net/nonav/ajax/refreshing-data/frames.html的一个实现,感觉也是定时刷新,通过setTimeOut()实现定时出发某个通讯请求。
我现在不知道这种定时刷新的实现能否达到要求。比如,如果做一个在线的股票系统,那么对实时要求应该比较高吧?我希望能最好能有一个可以参考的东西,我可以看看那个东西是怎么实现。
当然,我没有说定时刷新不好,只是不清楚这样做是否可以,如果能够证明这种实现没有问题,或者类似的系统都是这么实现的话,我当然也不会放弃这种实现方式,呵呵。

#6


这好像和股票系统差不多啊,你搜索一下,可能会有相关的。

#7


楼上是否知道类似的系统,我想看看源码。
看看这个部分是怎么实现,呵呵。

#8


你既然不想让客户端定时刷新,那就让服务器端时时把改动push给客户端吧。不过目前我还没发现有服务器主动请求浏览器的例子

我觉得用AJAX不是挺好吗。

#9


要么拉要么推
你可以考虑像163聊天室那样用servelet分发
具体杂做的俺不知道

#10


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

public class SocketWatch {

  private static void printUsage() {
    System.out.println("usage: java SocketWatch port");
  }

  public static void main(String[] args) {
    if (args.length < 1) {
      printUsage();
      return;
    }

    // The first argument is the port to listen on
    int port;
    try {
      port = Integer.parseInt(args[0]);
    }
    catch (NumberFormatException e) {
      printUsage();
      return;
    }

    try {
      // Establish a server socket to accept client connections
      // As each connection comes in, pass it to a handler thread
      ServerSocket ss = new ServerSocket(port);
      while (true) {
        Socket request = ss.accept();
        new HandlerThread(request).start();
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

class HandlerThread extends Thread {

  Socket s;

  public HandlerThread(Socket s) {
    this.s = s;
  }
import java.io.*;
import java.net.*;
import java.util.*;

public class HttpClient {

  private static void printUsage() {
    System.out.println("usage: java HttpClient host port");
  }

  public static void main(String[] args) {
    if (args.length < 2) {
      printUsage();
      return;
    }

    // Host is the first parameter, port is the second
    String host = args[0];
    int port;
    try {
      port = Integer.parseInt(args[1]);
    }
    catch (NumberFormatException e) {
      printUsage();
      return;
    }

    try {
      // Open a socket to the server
      Socket s = new Socket(host, port);

      // Start a thread to send keyboard input to the server
      new KeyboardInputManager(System.in, s).start();

      // Now print everything we receive from the socket 
      BufferedReader in = 
        new BufferedReader(new InputStreamReader(s.getInputStream()));
      String line;
      while ((line = in.readLine()) != null) {
        System.out.println(line);
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

class KeyboardInputManager extends Thread {

  InputStream in;
  Socket s;

  public KeyboardInputManager(InputStream in, Socket s) {
    this.in = in;
    this.s = s;
    setPriority(MIN_PRIORITY);  // socket reads should have a higher priority
                                // Wish I could use a select() !
    setDaemon(true);  // let the app die even when this thread is running
  }

  public void run() {
    try {
      BufferedReader keyb = new BufferedReader(new InputStreamReader(in));
      PrintWriter server = new PrintWriter(s.getOutputStream());

      String line;
      System.out.println("Connected... Type your manual HTTP request");
      System.out.println("------------------------------------------");
      while ((line = keyb.readLine()) != null) {
        server.print(line);
        server.print("\r\n");  // HTTP lines end with \r\n
        server.flush();
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

  public void run() {
    try {
      // Print each byte as it comes in from the socket
      InputStream in = s.getInputStream();
      byte[] bytes = new byte[1];
      while ((in.read(bytes)) != -1) {
        System.out.print((char)bytes[0]);
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

#11


import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;

import com.oreilly.servlet.HttpMessage;

public class SocketChatApplet extends Applet implements Runnable {

  static final int PORT = 2428;

  DataInputStream serverStream;

  TextArea text;
  Label label;
  TextField input;
  Thread thread;
  String user;

  public void init() {
    // Check if this applet was loaded directly from the filesystem.
    // If so, explain to the user that this applet needs to be loaded
    // from a server in order to communicate with that server's servlets.
    URL codebase = getCodeBase();
    if (!"http".equals(codebase.getProtocol())) {
      System.out.println();
      System.out.println("*** Whoops! ***");
      System.out.println("This applet must be loaded from a web server.");
      System.out.println("Please try again, this time fetching the HTML");
      System.out.println("file containing this servlet as");
      System.out.println("\"http://server:port/file.html\".");
      System.out.println();
      System.exit(1);  // Works only from appletviewer
                       // Browsers throw an exception and muddle on
    }

    // Get this user's name from an applet parameter set by the servlet
    // We could just ask the user, but this demonstrates a
    // form of servlet->applet communication.
    user = getParameter("user");
    if (user == null) user = "anonymous";

    // Set up the user interface...
    // On top, a large TextArea showing what everyone's saying.
    // Underneath, a labeled TextField to accept this user's input.
    text = new TextArea();
    text.setEditable(false);
    label = new Label("Say something: ");
    input = new TextField();
    input.setEditable(true);

    setLayout(new BorderLayout());
    Panel panel = new Panel();
    panel.setLayout(new BorderLayout());

    add("Center", text);
    add("South", panel);

    panel.add("West", label);
    panel.add("Center", input);
  }

  public void start() {
    thread = new Thread(this);
    thread.start();
  }

  String getNextMessage() {
    String nextMessage = null;
    while (nextMessage == null) {
      try {
        // Connect to the server if we haven't before
        if (serverStream == null) {
          Socket s = new Socket(getCodeBase().getHost(), PORT);
          serverStream = new DataInputStream(
                         new BufferedInputStream(
                         s.getInputStream()));
        }
  
        // Read a line
        nextMessage = serverStream.readLine();
      }
      catch (SocketException e) {
        // Can't connect to host, report it and wait before trying again
        System.out.println("Can't connect to host: " + e.getMessage());
        serverStream = null;
        try { Thread.sleep(5000); } catch (InterruptedException ignored) { }
      }
      catch (Exception e) {
        // Some other problem, report it and wait before trying again
        System.out.println("General exception: " +
          e.getClass().getName() + ": " + e.getMessage());
        try { Thread.sleep(1000); } catch (InterruptedException ignored) { }
      }
    }
    return nextMessage + "\n";
  }

  public void run() {
    while (true) {
      text.appendText(getNextMessage());
    }
  }

  public void stop() {
    thread.stop();
    thread = null;
  }

  void broadcastMessage(String message) {
    message = user + ": " + message;  // Pre-pend the speaker's name
    try {
      URL url = new URL(getCodeBase(), "/servlet/ChatServlet");
      HttpMessage msg = new HttpMessage(url);
      Properties props = new Properties();
      props.put("message", message);
      msg.sendPostMessage(props);
    }
    catch (SocketException e) {
      // Can't connect to host, report it and abandon the broadcast
      System.out.println("Can't connect to host: " + e.getMessage());
    }
    catch (FileNotFoundException e) {
      // Servlet doesn't exist, report it and abandon the broadcast
      System.out.println("Resource not found: " + e.getMessage());
    }
    catch (Exception e) {
      // Some other problem, report it and abandon the broadcast
      System.out.println("General exception: " +
        e.getClass().getName() + ": " + e.getMessage());
    }
  }

  public boolean handleEvent(Event event) {
    switch (event.id) {
      case Event.ACTION_EVENT:
        if (event.target == input) {
          broadcastMessage(input.getText());
          input.setText("");
          return true;
        }
    }
    return false;
  }
}

#12


to usaspy(行走的鱼):
呵呵,我没有说AJAX不好呀,只是我还对它不是太熟悉。我需要一个有力的证据说明它适合目前这个需求而以,如果您见过类似用AJAX,或者说xmlHTTP写的实时系统的话,我可以看看,考虑使用这个东西:)

to 108041217(金箔):
谢谢您的代码,我先研究一下,呵呵

#13


js+xmlhttp 我用过一点,感觉很简单的。很快就能入门,你可以看看。

#14


to usaspy(行走的鱼):
AJAX这个东西,我前几天看过一些。但是,我现在无法确定这个技术对于我这个需求的可行性。所以,我一直喋喋不休的想要一个类似的系统代码来看:p
另外,考虑到js调试起来可能比较麻烦,所以我希望能够有更好的解决方案,呵呵。


to 108041217(金箔):
您的代码,我刚才看了一下,感觉和我说的东西不太一样。我希望的是服务器的内容变了之后,客户端能够立刻反映出来。可能是我比较的愚钝,没有看出您的代码中哪里能够解决我的问题,望指点,呵呵。

#15


"我希望的是服务器的内容变了之后,客户端能够立刻反映出来。"

你还是用C/S可能比较好。B/S结构设计的时候就是由客户端发请求,服务器只是响应请求。

#16


谢谢usaspy(行走的鱼),那我再想想吧,看看有没有什么好的解决方案,呵呵

#17


up

#18


找到了一些东西,也许对大家有些用,贴出来共享一下,呵呵。

两个框架(HTTP-based publish/subscribe framework),还没有仔细看,有兴趣的朋友可以看看
http://www.pushlets.com/
http://www.mod-pubsub.org/docs/faq.html

一些其他的框架:
jsonrpc:http://oss.metaparadigm.com/jsonrpc/
buffalo:http://www.amowa.net/buffalo/

#19


学习

#1


以我多年的经验,还是定时刷新吧,通过applet的方式局限性太大,其他一般也没什么太好的方案,要不就是使用activeX还可能不错

#2


B/S结构做实时的东西不太好吧

#3


to  majy(小马哥):
由于对实时性要求比较高,所以原则上尽量不希望用定时刷新的方式。有没有什么可以参考的东西用您提到的方法实现的?当然我说的是B/S结构的

to minisun2000(天生不专一):
恩,是不太好,不过想做一个,呵呵


----------------------
另外,我还想到一些技术。但是不知道是否能够用到这个东西上来:JMX, AJAX, JMS
由于我对这些技术不是太熟悉,不知道是否适用,熟悉这些技术的朋友,或者做过类似系统的朋友欢迎您们的建议:)

#4


你只是希望不定时刷新吗,不知道xmlhttp能否满足你的要求

#5


to usaspy(行走的鱼):
您说的是AJAX吗?呵呵
那个东西,好像也是定时的进行通讯吧。
我看了https://bpcatalog.dev.java.net/nonav/ajax/refreshing-data/frames.html的一个实现,感觉也是定时刷新,通过setTimeOut()实现定时出发某个通讯请求。
我现在不知道这种定时刷新的实现能否达到要求。比如,如果做一个在线的股票系统,那么对实时要求应该比较高吧?我希望能最好能有一个可以参考的东西,我可以看看那个东西是怎么实现。
当然,我没有说定时刷新不好,只是不清楚这样做是否可以,如果能够证明这种实现没有问题,或者类似的系统都是这么实现的话,我当然也不会放弃这种实现方式,呵呵。

#6


这好像和股票系统差不多啊,你搜索一下,可能会有相关的。

#7


楼上是否知道类似的系统,我想看看源码。
看看这个部分是怎么实现,呵呵。

#8


你既然不想让客户端定时刷新,那就让服务器端时时把改动push给客户端吧。不过目前我还没发现有服务器主动请求浏览器的例子

我觉得用AJAX不是挺好吗。

#9


要么拉要么推
你可以考虑像163聊天室那样用servelet分发
具体杂做的俺不知道

#10


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

public class SocketWatch {

  private static void printUsage() {
    System.out.println("usage: java SocketWatch port");
  }

  public static void main(String[] args) {
    if (args.length < 1) {
      printUsage();
      return;
    }

    // The first argument is the port to listen on
    int port;
    try {
      port = Integer.parseInt(args[0]);
    }
    catch (NumberFormatException e) {
      printUsage();
      return;
    }

    try {
      // Establish a server socket to accept client connections
      // As each connection comes in, pass it to a handler thread
      ServerSocket ss = new ServerSocket(port);
      while (true) {
        Socket request = ss.accept();
        new HandlerThread(request).start();
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

class HandlerThread extends Thread {

  Socket s;

  public HandlerThread(Socket s) {
    this.s = s;
  }
import java.io.*;
import java.net.*;
import java.util.*;

public class HttpClient {

  private static void printUsage() {
    System.out.println("usage: java HttpClient host port");
  }

  public static void main(String[] args) {
    if (args.length < 2) {
      printUsage();
      return;
    }

    // Host is the first parameter, port is the second
    String host = args[0];
    int port;
    try {
      port = Integer.parseInt(args[1]);
    }
    catch (NumberFormatException e) {
      printUsage();
      return;
    }

    try {
      // Open a socket to the server
      Socket s = new Socket(host, port);

      // Start a thread to send keyboard input to the server
      new KeyboardInputManager(System.in, s).start();

      // Now print everything we receive from the socket 
      BufferedReader in = 
        new BufferedReader(new InputStreamReader(s.getInputStream()));
      String line;
      while ((line = in.readLine()) != null) {
        System.out.println(line);
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

class KeyboardInputManager extends Thread {

  InputStream in;
  Socket s;

  public KeyboardInputManager(InputStream in, Socket s) {
    this.in = in;
    this.s = s;
    setPriority(MIN_PRIORITY);  // socket reads should have a higher priority
                                // Wish I could use a select() !
    setDaemon(true);  // let the app die even when this thread is running
  }

  public void run() {
    try {
      BufferedReader keyb = new BufferedReader(new InputStreamReader(in));
      PrintWriter server = new PrintWriter(s.getOutputStream());

      String line;
      System.out.println("Connected... Type your manual HTTP request");
      System.out.println("------------------------------------------");
      while ((line = keyb.readLine()) != null) {
        server.print(line);
        server.print("\r\n");  // HTTP lines end with \r\n
        server.flush();
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

  public void run() {
    try {
      // Print each byte as it comes in from the socket
      InputStream in = s.getInputStream();
      byte[] bytes = new byte[1];
      while ((in.read(bytes)) != -1) {
        System.out.print((char)bytes[0]);
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

#11


import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;

import com.oreilly.servlet.HttpMessage;

public class SocketChatApplet extends Applet implements Runnable {

  static final int PORT = 2428;

  DataInputStream serverStream;

  TextArea text;
  Label label;
  TextField input;
  Thread thread;
  String user;

  public void init() {
    // Check if this applet was loaded directly from the filesystem.
    // If so, explain to the user that this applet needs to be loaded
    // from a server in order to communicate with that server's servlets.
    URL codebase = getCodeBase();
    if (!"http".equals(codebase.getProtocol())) {
      System.out.println();
      System.out.println("*** Whoops! ***");
      System.out.println("This applet must be loaded from a web server.");
      System.out.println("Please try again, this time fetching the HTML");
      System.out.println("file containing this servlet as");
      System.out.println("\"http://server:port/file.html\".");
      System.out.println();
      System.exit(1);  // Works only from appletviewer
                       // Browsers throw an exception and muddle on
    }

    // Get this user's name from an applet parameter set by the servlet
    // We could just ask the user, but this demonstrates a
    // form of servlet->applet communication.
    user = getParameter("user");
    if (user == null) user = "anonymous";

    // Set up the user interface...
    // On top, a large TextArea showing what everyone's saying.
    // Underneath, a labeled TextField to accept this user's input.
    text = new TextArea();
    text.setEditable(false);
    label = new Label("Say something: ");
    input = new TextField();
    input.setEditable(true);

    setLayout(new BorderLayout());
    Panel panel = new Panel();
    panel.setLayout(new BorderLayout());

    add("Center", text);
    add("South", panel);

    panel.add("West", label);
    panel.add("Center", input);
  }

  public void start() {
    thread = new Thread(this);
    thread.start();
  }

  String getNextMessage() {
    String nextMessage = null;
    while (nextMessage == null) {
      try {
        // Connect to the server if we haven't before
        if (serverStream == null) {
          Socket s = new Socket(getCodeBase().getHost(), PORT);
          serverStream = new DataInputStream(
                         new BufferedInputStream(
                         s.getInputStream()));
        }
  
        // Read a line
        nextMessage = serverStream.readLine();
      }
      catch (SocketException e) {
        // Can't connect to host, report it and wait before trying again
        System.out.println("Can't connect to host: " + e.getMessage());
        serverStream = null;
        try { Thread.sleep(5000); } catch (InterruptedException ignored) { }
      }
      catch (Exception e) {
        // Some other problem, report it and wait before trying again
        System.out.println("General exception: " +
          e.getClass().getName() + ": " + e.getMessage());
        try { Thread.sleep(1000); } catch (InterruptedException ignored) { }
      }
    }
    return nextMessage + "\n";
  }

  public void run() {
    while (true) {
      text.appendText(getNextMessage());
    }
  }

  public void stop() {
    thread.stop();
    thread = null;
  }

  void broadcastMessage(String message) {
    message = user + ": " + message;  // Pre-pend the speaker's name
    try {
      URL url = new URL(getCodeBase(), "/servlet/ChatServlet");
      HttpMessage msg = new HttpMessage(url);
      Properties props = new Properties();
      props.put("message", message);
      msg.sendPostMessage(props);
    }
    catch (SocketException e) {
      // Can't connect to host, report it and abandon the broadcast
      System.out.println("Can't connect to host: " + e.getMessage());
    }
    catch (FileNotFoundException e) {
      // Servlet doesn't exist, report it and abandon the broadcast
      System.out.println("Resource not found: " + e.getMessage());
    }
    catch (Exception e) {
      // Some other problem, report it and abandon the broadcast
      System.out.println("General exception: " +
        e.getClass().getName() + ": " + e.getMessage());
    }
  }

  public boolean handleEvent(Event event) {
    switch (event.id) {
      case Event.ACTION_EVENT:
        if (event.target == input) {
          broadcastMessage(input.getText());
          input.setText("");
          return true;
        }
    }
    return false;
  }
}

#12


to usaspy(行走的鱼):
呵呵,我没有说AJAX不好呀,只是我还对它不是太熟悉。我需要一个有力的证据说明它适合目前这个需求而以,如果您见过类似用AJAX,或者说xmlHTTP写的实时系统的话,我可以看看,考虑使用这个东西:)

to 108041217(金箔):
谢谢您的代码,我先研究一下,呵呵

#13


js+xmlhttp 我用过一点,感觉很简单的。很快就能入门,你可以看看。

#14


to usaspy(行走的鱼):
AJAX这个东西,我前几天看过一些。但是,我现在无法确定这个技术对于我这个需求的可行性。所以,我一直喋喋不休的想要一个类似的系统代码来看:p
另外,考虑到js调试起来可能比较麻烦,所以我希望能够有更好的解决方案,呵呵。


to 108041217(金箔):
您的代码,我刚才看了一下,感觉和我说的东西不太一样。我希望的是服务器的内容变了之后,客户端能够立刻反映出来。可能是我比较的愚钝,没有看出您的代码中哪里能够解决我的问题,望指点,呵呵。

#15


"我希望的是服务器的内容变了之后,客户端能够立刻反映出来。"

你还是用C/S可能比较好。B/S结构设计的时候就是由客户端发请求,服务器只是响应请求。

#16


谢谢usaspy(行走的鱼),那我再想想吧,看看有没有什么好的解决方案,呵呵

#17


up

#18


找到了一些东西,也许对大家有些用,贴出来共享一下,呵呵。

两个框架(HTTP-based publish/subscribe framework),还没有仔细看,有兴趣的朋友可以看看
http://www.pushlets.com/
http://www.mod-pubsub.org/docs/faq.html

一些其他的框架:
jsonrpc:http://oss.metaparadigm.com/jsonrpc/
buffalo:http://www.amowa.net/buffalo/

#19


学习

#20