【问题标题】:ObjectOutputStream not updatingObjectOutputStream 未更新
【发布时间】:2015-05-02 19:32:02
【问题描述】:

我在服务器上工作,服务器类为每个连接的客户端创建一个新线程,当客户端连接时,ObjectOutputStream 不会在多个连接的客户端上刷新。卡在最后连接的客户端OutputObjectStream

这是服务器初始化函数

    private void init(Server s)
    {
    ServerSocket server = null;
    Socket c = null;
    ServerThread tmp = null;
    try
    {
        this.db = new Database();
        server = new ServerSocket(6789);
        System.out.println("Listening on 6789");
        while(true)
        {
            c = server.accept();
            tmp = new ServerThread(c, s);
            clients.add(tmp);
            new Thread(tmp).start();
        }
    }catch(IOException | SQLException e)
    {
        e.printStackTrace();
        System.exit(1);
    }   

这是ServerThread的构造函数和运行函数:

    package server;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import scripts.Response;

import com.sun.rowset.CachedRowSetImpl;

public class ServerThread implements Runnable
{
public static ObjectOutputStream output;
private static ObjectInputStream input;
private Socket client = null;
private Server server = null;
private Response line = null;
private String usr;

public ServerThread(Socket c, Server server) throws IOException
{
    this.client = c;
    this.server  = server;
    this.output = new ObjectOutputStream(client.getOutputStream());
    output.flush();
    output.reset();
    this.input  = new ObjectInputStream(client.getInputStream());
}

public void run()
{
    try
    {               
        System.out.println("Client connected");

        write(new Response("200","Time to login"));
        while((line = (Response)input.readObject()) != null)
        {
            read_code(line);
        }
    }catch(EOFException e){
        System.out.println("EOFException, probably end of stream");

    }catch(IOException e)
    {
        e.printStackTrace();
        Thread.currentThread().interrupt();
    }catch(ClassNotFoundException cnfe)
    {
        cnfe.printStackTrace();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public void alert_user(String q) throws IOException
{
    System.out.println("In thread "+q);
    write(new Response("404", "You are being alerted!"));
}

private void read_code(Response response) throws IOException, SQLException
{
    HashMap tmp_response = response.extract_map();
    switch ((String)tmp_response.get("code"))
    {
        case "420":
            usr_login(tmp_response);
            break;
        case "430":
            select_query((String)tmp_response.get("to_select"), (String)tmp_response.get("table"), (String)tmp_response.get("rest"));
            break;
        case "431":
            /**
             * server.alertUsers(ArrayList<String> usernames); if there is users that has to be alerted
             */
            insert_query((String)tmp_response.get("table"), (ArrayList<String>)tmp_response.get("columns"), (ArrayList<String>)tmp_response.get("values"));
            break;
        default:
            System.out.println("Unrecognized command");
    }
}

private void usr_login(HashMap tmp_response) throws IOException
{
    String usr = (String) tmp_response.get("username");
    String pass = (String) tmp_response.get("password");
    boolean login = server.query_login(usr, pass);
    System.out.println(login);
    if(login)
    {
        write(new Response("9001", "Login Successfull!"));
        this.usr = usr;
    }else
        write(new Response("8999", "Login Unsuccessfull!"));
}

private void insert_query(String table, ArrayList<String> columns, ArrayList<String> values) throws IOException, SQLException
{
    CachedRowSetImpl rows = server.insert_query(table, columns, values);
    write(new Response("3", rows));
}

private void select_query(String to_select, String table, String rest) throws SQLException, IOException
{
    CachedRowSetImpl rows = server.select_query(to_select, table, rest);
    write(new Response("2", rows));
}

private void write(Response resp) throws IOException
{
    System.out.println(output.toString());
    System.out.println(client.toString());
    output.reset();
    output.writeObject(resp);
    output.flush();
}

public String get_user()
{
    return usr;
}

}

所以当我尝试打印出对象时,我得到了这个

    Client connected
    java.io.ObjectOutputStream@3933c336 (New client (1) connected)
    Client connected
    java.io.ObjectOutputStream@5adada9e (New client (2) connected)      
    java.io.ObjectOutputStream@5adada9e (Sending to first client)

编辑 为什么 ObjectOutputStream 不会刷新,而是使用从一开始就分配给它的输出流,而不是最新的?

编辑 忘记加写功能了,打印在哪里

编辑 添加了整个 ServerThread 类

【问题讨论】:

  • write() 只为每个客户端调用一次。也许read_code 有另一个电话,在这种情况下,我也需要看到它才能接听。
  • 现在添加了整个 ServerThread

标签: java multithreading sockets serversocket objectoutputstream


【解决方案1】:

这是一个静态混淆的例子。

Java 中的关键字static 表示完全独立于此类实例的组件(变量或方法)。对于变量,这意味着只有一个变量副本供所有实例共享,而不是每个实例都有一个单独的副本(即非静态变量)。

因为实例共享静态变量,所以它的值对于所有实例总是相同的。如果您在一个实例中更改该值,它也会在所有其他实例中更改。


在您的情况下,您将static 用于ObjectInputStreamObjectOutputStream,因此它们无法更改:关键字final 使变量无法更改。请注意,这只会使分配变得不可能,不会更改分配对象的内部值(例如,通过设置器)。它只是阻止您创建一个新对象并将其放入最终变量中。

【讨论】:

    猜你喜欢
    • 2012-01-12
    • 2013-05-02
    • 2016-05-31
    • 1970-01-01
    • 2011-06-17
    • 2013-04-14
    • 1970-01-01
    • 2015-11-20
    • 2012-08-08
    相关资源
    最近更新 更多