【问题标题】:Java - client-server clockJava - 客户端-服务器时钟
【发布时间】:2015-02-27 19:58:35
【问题描述】:

我有点卡在一个问题上。我有一个 Java 客户端-服务器应用程序,其中多个客户端可以连接到服务器。现在我有一个循环操作,它正在获取当前时间(对应于我在服务器端的 ClockTask)。但我真的不知道如何将这个时间数据传输到所有连接的客户端。我猜它应该由 ObjectOutputStream 以某种方式完成,但如果有人能提示我,那就太好了。

这是我的服务器代码,以及运行客户端连接的线程:

 public class Server {

 public static void main(String[] args) throws IOException {

        ServerSocket serverSocket = null;

        boolean listeningSocket = true;
        try {
            serverSocket = new ServerSocket(11111);
        } catch (IOException e) {
            System.err.println("Could not listen on port: 11111");
        }

        while(listeningSocket){
            System.out.println("Waiting for a client to connect...");
            Socket clientSocket = serverSocket.accept();
            System.out.println("Client connected!");
            ConnectThread ct = new ConnectThread(clientSocket);
            ct.start();

        }
        serverSocket.close();       
    }
}

连接线程:

public class ConnectThread extends Thread{

private Socket socket = null;


public ConnectThread(Socket socket) {

super("ConnectThread");
this.socket = socket;

}

@Override
public void run(){
ObjectOutputStream serverOutputStream = null;
ObjectInputStream serverInputStream = null;
try {
    System.out.println("check");
    serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
    System.out.println("check");
    serverInputStream = new ObjectInputStream(socket.getInputStream());
    serverOutputStream.writeInt(42);
    System.out.println("check");
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
finally{
    try {
        serverOutputStream.close();
        serverInputStream.close();              
        socket.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

}

和客户:

public class Client {

public static void main(String[] arg) {


Socket socketConnection = null;
ObjectOutputStream clientOutputStream = null;
ObjectInputStream clientInputStream = null;
        try {

    socketConnection = new Socket("127.0.0.1", 11111);

    clientOutputStream = new ObjectOutputStream(
            socketConnection.getOutputStream());
    clientInputStream = new ObjectInputStream(
            socketConnection.getInputStream());
    System.out.println("check");
    System.out.println(clientInputStream.readInt()); // HERE'S WHERE THE EXCEPTION OCCURS

} catch (Exception e) {
    System.out.println("The following exception has occured and was caught:");
    System.out.println(e);
}

finally{
    try {
        clientOutputStream.close();
        clientInputStream.close();
        socketConnection.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}
}

时钟任务:

public class ClockTask extends TimerTask {


@Override
public void run() {
    DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    Calendar c = Calendar.getInstance();
    System.out.println(dateFormat.format(c.getTime()));
    //some object output stream here??
}

}

【问题讨论】:

  • 既然存在这么多(更方便|对用户更容易|错误更少)[1] RPC 协议,为什么还要使用Serializable? [1] 选择您的选择;一般来说,网络上任何支持 RPC 的协议都至少遵循上述两个特征
  • 你可以试试serverOutputStream.flush(),然后在serverOutputStream.writeInt(42);之后稍微延迟一下,这样客户端就有机会在服务器关闭连接之前消费响应吗?

标签: java multithreading timer client server


【解决方案1】:

我不建议发送 Calendar 对象,因为它是一个使用大约 2900 字节的非常昂贵的对象。相反,您可以通过使用 8 个字节的 DataOutputStream 发送一个长值。

注意:您需要纠正客户端和服务器之间的延迟,否则时间总是会延迟。

解决这个问题的一个简单方法是让客户端向服务器发送一条带有时间戳的消息,服务器使用它自己的时间戳进行响应,您可以假设延迟是往返时间的一半。然后,您可以应用 EWMA(指数加权移动平均线)来获得服务器和客户端时钟差异的原因平均值。

【讨论】:

  • 是的,我也没有考虑整个日历,更像是单独发送日期。但是,如果我尝试使用简单的 OOS 来执行此操作,我会收到很多“套接字关闭错误”并且事情会变得一团糟。
  • @user4359659 您可能会发现数据流要简单得多。更少的魔法发生。只是发送简单的原语。
猜你喜欢
  • 2017-06-19
  • 1970-01-01
  • 1970-01-01
  • 2012-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-09
  • 1970-01-01
相关资源
最近更新 更多