Java 连接到服务器,发送字符串并接收对象-BufferedReader not';准备好了吗;?

Java 连接到服务器,发送字符串并接收对象-BufferedReader not';准备好了吗;?,java,networking,Java,Networking,服务器: public Server() { gui = new GUI(); try { socket = new ServerSocket(2000); while (true) { Socket client = socket.accept(); gui.append("Client accepted."); if (inetAddrFound(client.ge

服务器:

    public Server() {
    gui = new GUI();
    try {
        socket = new ServerSocket(2000);
        while (true) {
            Socket client = socket.accept();
            gui.append("Client accepted.");
            if (inetAddrFound(client.getInetAddress().getHostName())) {
                Thread thread = new Thread(new IncomingClient(client));
                threads.put(client, thread);
                thread.start();
            }

        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public class IncomingClient implements Runnable {

    BufferedReader reader;
    Socket sock;

    public IncomingClient(Socket socket) {
        gui.append("Incoming socket class instantiated.");
        try {
            this.sock = socket;
            InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());
            reader = new BufferedReader(streamReader);
        } catch (Exception e) {
            for (StackTraceElement s : e.getStackTrace()) {
                gui.append(s.toString());
            }
        }
    }

    @Override
    public void run() {
        String message;
        try {
            while (true) {
                gui.append("Trying to see if reader.readLine == null");
                if (!reader.ready()) {
                    System.out.println("Reader is not ready.");
                    continue;
                }
                if ((message = reader.readLine()) != null && !Thread.currentThread().isInterrupted()) {
                    System.out.println("Reader is not null.");
                    System.out.println("Message = " + message);
                    gui.append(message);
                    if (idFound(message)) {
                        ObjectOutputStream stream = (ObjectOutputStream) sock.getOutputStream();
                        stream.writeObject(spooker);
                        stream.close();
                        threads.get(sock).interrupt();
                        threads.remove(sock);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
客户:

private void connect() {
    try {
        socket = new Socket(decode(ADDR), Integer.parseInt(decode(PORT)));
        ois = new ObjectInputStream(socket.getInputStream());
        writer = new PrintWriter(socket.getOutputStream());
        writer.println(String.valueOf(encode(getMotherboardSN())));
        writer.flush;
        writer.close;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public class IncomingSpookerObject implements Runnable {

    @Override
    public void run() {
        SpookerObject object;
        try {
            while ((object = (SpookerObject) ois.readObject()) != null && !Thread.currentThread().isInterrupted()) {
                spooker = (SpookerObject) ois.readObject();
                thread.interrupt();
                System.out.println(spooker.getX());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
我的目标是连接到服务器,将用户cpu id(每台计算机的唯一标识符)发送到服务器(cpu id是一个字符串),服务器将读取cpu id,如果用户已注册(例如,如果他们的cpu id在数据库中),则将向他们发送一个对象(Spooker对象)

spooker对象是一个测试对象,它只保存int x=4和一个返回x,getX()的方法

我之所以这么做是为了防止软件被泄露。将来,spooker对象将包含启动客户端软件的信息(例如GUI大小、GUI标题、字符串值等)。这是为了使软件在连接到服务器并检索特定信息时更难泄漏

我希望我已经尽可能清楚了

阿尔奇

编辑-更新的服务器对象

服务器输出-

客户接受了。 已实例化传入套接字类。 正在尝试查看reader.readLine==null

读者还没准备好。 读者还没准备好。 读者还没准备好。 读者还没准备好。 读者还没准备好。 读者还没准备好

它不断地打印出来——为什么读者从来没有准备好

编辑; 增加:

writer.println writer.flush();writer.close()


服务器正在尝试读取一行永不结束的内容。在connect方法中,应该关闭输出流

更新

下面是一个有效的例子。事实上,不能关闭输出流,因为它会关闭底层套接字

服务器:

public class Server {
    private static final Logger LOG = Logger.getLogger(Server.class.getName());

    public static void main(String[] args) {
    int port = args.length > 0 ? Integer.parseInt(args[0]) : 2000;
    try (ServerSocket socket = new ServerSocket(port)) {
            while (true) {
                Socket client = socket.accept();
                System.out.println("Client accepted.");
                Thread thread = new Thread(new IncomingClient(client));
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class IncomingClient implements Runnable {
        private final Socket sock;
        private final SpookerObject spooker = new SpookerObject();

        public IncomingClient(Socket socket) {
            System.out.println("Incoming socket class instantiated.");
            this.sock = socket;
        }

        @Override
        public void run() {
            try (InputStream istream = sock.getInputStream();
                    Reader reader = new InputStreamReader(istream);
                    BufferedReader in = new BufferedReader(reader);
                    OutputStream ostream = sock.getOutputStream();
                    ObjectOutputStream out = new ObjectOutputStream(ostream)) {
                String message = in.readLine();
                if (message != null && idFound(message)) {
                    while (!Thread.currentThread().isInterrupted()
                            && sock.isConnected()) {
                        System.out.println("Reader is not null.");
                        System.out.println("Message = " + message);
                        out.writeObject(spooker);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    sock.close();
                } catch (IOException ex) {
                    LOG.log(Level.SEVERE, null, ex);
                }
            }
        }

        private boolean idFound(String id) {
            return "abcdef".equals(id);
        }
    }
}
客户:

public class Client implements Closeable {
    private static final Logger LOG = Logger.getLogger(Client.class.getName());

    private final Socket socket;
    private final ObjectInputStream ois;

    public static void main(String[] args) {
        try {
            InetAddress server = InetAddress.getByName(args[0]);
            int port = Integer.parseInt(args[1]);
            String cpuId = args[2];
            try (Client client = new Client(server, port, cpuId)) {
                for (int i = 0; i < 3; ++i) {
                    System.out.println(client.readSpooker());
                }
            }
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }

    public Client(InetAddress address, int port, String cpuId)
            throws IOException {
        boolean ok = false;
        socket = new Socket(address, port);
        try {
            OutputStream stream = socket.getOutputStream();
            Writer writer = new OutputStreamWriter(stream, "UTF-8");
            PrintWriter out = new PrintWriter(writer);
            out.println(cpuId);
            out.flush();
            ois = new ObjectInputStream(socket.getInputStream());
            ok = true;
        } finally {
            if (!ok) {
                socket.close();
            }
        }
    }

    @Override
    public void close() throws IOException {
        try {
            if (ois != null) {
                ois.close();
            }
        } finally {
            socket.close();
        }
    }

    public SpookerObject readSpooker() throws IOException {
        try {
            return (SpookerObject)ois.readObject();
        } catch (ClassNotFoundException ex) {
            LOG.log(Level.SEVERE, null, ex);
            throw new IOException(ex.getMessage());
        }
    }
}
公共类客户端实现可关闭{
私有静态最终记录器LOG=Logger.getLogger(Client.class.getName());
专用终端插座;
私人最终目标输出ois;
公共静态void main(字符串[]args){
试一试{
InetAddress服务器=InetAddress.getByName(args[0]);
int port=Integer.parseInt(args[1]);
字符串cpuId=args[2];
try(客户机=新客户机(服务器、端口、cpuId)){
对于(int i=0;i<3;++i){
System.out.println(client.readSpooker());
}
}
}捕获(IOEX异常){
LOG.LOG(Level.SEVERE,null,ex);
}
}
公共客户端(InetAddress地址、int端口、字符串cpuId)
抛出IOException{
布尔ok=false;
套接字=新套接字(地址、端口);
试一试{
OutputStream=socket.getOutputStream();
Writer Writer=新的输出流Writer(流,“UTF-8”);
PrintWriter out=新的PrintWriter(writer);
out.println(cpuId);
out.flush();
ois=newObjectInputStream(socket.getInputStream());
ok=正确;
}最后{
如果(!ok){
socket.close();
}
}
}
@凌驾
public void close()引发IOException{
试一试{
如果(ois!=null){
ois.close();
}
}最后{
socket.close();
}
}
public SpookerObject readSpooker()引发IOException{
试一试{
返回(SpookerObject)ois.readObject();
}捕获(ClassNotFoundException ex){
LOG.LOG(Level.SEVERE,null,ex);
抛出新IOException(例如getMessage());
}
}
}

您没有发送带有客户端数据的CR,因此就服务器而言,还没有完整的行可读取。尝试将
writer.write()
更改为
writer.println()

只需删除
ready()
测试,然后
继续。这没有意义。您只需旋转循环,直到至少有一个字节可以在不阻塞的情况下读取,然后很可能会在
readLine()
中阻塞,因为它会阻塞,直到可以读取整行


您还需要决定是发送行还是对象。不能通过同一个插座同时执行这两项操作

我设法弄明白了。我不得不用, object=ois.readObject(); 对象实例

不是 ois.readObject instanceOf

等等


很抱歉回答得很简短,很忙。

实际问题是什么?你有错误吗?您调试过吗?@SteveSmith客户端似乎正在连接到服务器,但此代码
(message=reader.readLine())!=null
返回null或根本不运行-因为
gui.append(消息)
不运行。刚刚调试过。它一直运行,然后reader.readLine为null。可能是服务器试图在客户端发送数据之前读取数据。尝试让服务器等待@SteveSmith添加了
reader.ready()
,但输出仍然是一样的。我不明白IncomingSpookerObject类的目的是为了阻止发送/接收更多的数据,比如对象数据。好的,至少做一次println,因为@SteveSmith写了这个问题仍然没有解决。bufferedreader从未就绪。确定,然后删除对reader.ready()的测试。它的目的是什么?`Socket.isConnected()`在对等机断开连接时不会神奇地变成false。不能在同一个套接字上混合使用行和对象I/O。你声称这段代码是有效的,这很难让人相信。改变了-但它仍然看不懂。BufferedReader似乎从未准备好。他正在发送一个带有客户端数据的行终止符。他正在调用
println()
,这正是他所做的。他现在正在调用,但我写答案时他没有。我不同意:服务器从输入流读取行,并在输出流上写入对象。这没什么错。我正在努力理解这是如何解决问题的
instanceof
没有在任何地方使用?@SteveSmith在更新版本it i中