【问题标题】:Java sending objects from queue or stack over TCP socketJava 通过 TCP 套接字从队列或堆栈发送对象
【发布时间】:2013-10-01 05:19:57
【问题描述】:

我想使用 TCP 在客户端/服务器之间发送/接收 12 个对象。对象是唯一的,但顺序始终相同。例如:客户端总是以发送“对象 1”开始,服务器总是以“对象 2”响应。如何设置队列或堆栈来执行此操作并仅使用 java 标准库同步对象的发送/接收?我已经处理了下面的代码(来自 1 个包的 3 个类文件),但它不起作用(文件结尾错误),但它显示了我在哪里:

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

class SimpleClient {
    public static void main(String args[]){
        int counter = 0;
        try{
            Socket s = new Socket("localhost",2002);
            OutputStream os = s.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(os);
            testobject to = new testobject(1,"object 1","field1","field2","field3","field4");
            System.out.println("sending object 1"); //debug
            oos.writeObject(to);
            //Socket ss = s.accept();
            InputStream is = s.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(is);
            testobject too = (testobject)ois.readObject();
            while (counter != 2) {
                while ( too.value != 3 ) {
                    if (to==null) {
                        System.out.println("object is null!");
                    } else if (to.value==1){
                        System.out.println("receiving object 2"); //debug
                        System.out.println(to.id);
                        os = s.getOutputStream();
                        oos = new ObjectOutputStream(os);
                        testobject to0 = new testobject(2,"object 3","field1","field2","field3","field4");
                        oos.writeObject(to0);
                        System.out.println("object 3 sent!");
                    } else if (to.value==2){
                        System.out.println("receiving object 4"); //debug
                        System.out.println(to.id);
                        os = s.getOutputStream();
                        oos = new ObjectOutputStream(os);
                        testobject to0 = new testobject(3,"object 5","field1","field2","field3","field4");
                        oos.writeObject(to0);
                        System.out.println("sending object 5");
                    }
                }
                is.close();
                s.close();
                //System.out.println((String)ois.readObject());
                counter = counter + 1;
            }
            oos.close();
            os.close();
            s.close();
        } catch(Exception e) {
            System.out.println(e);
        }
    }
}

class SimpleServer {
    public static void main(String args[]) {
        int port = 2002;
        int counter = 0;
        try {
            ServerSocket ss = new ServerSocket(port);
            while (counter != 1) {
                Socket s = ss.accept();
                InputStream is = s.getInputStream();
                ObjectInputStream ois = new ObjectInputStream(is);
                testobject to = (testobject)ois.readObject();
                while ( to.value != 1 ) {
                    if (to==null) {
                        System.out.println("object is null!");
                    } else if (to.value==1){
                        System.out.println("receiving object 1"); //debug
                        System.out.println(to.id);
                        OutputStream os = s.getOutputStream();
                        ObjectOutputStream oos = new ObjectOutputStream(os);
                        testobject to0 = new testobject(2,"object 2","field1","field2","field3","field4");
                        oos.writeObject(to0);
                        System.out.println("sending object 2");
                    } else if (to.value==2){
                        System.out.println("receiving object 3"); //debug
                        System.out.println(to.id);
                        OutputStream os = s.getOutputStream();
                        ObjectOutputStream oos = new ObjectOutputStream(os);
                        testobject to0 = new testobject(4,"object 4","field1","field2","field3","field4");
                        oos.writeObject(to0);
                        System.out.println("sending object 4");
                    }
                }
                is.close();
                s.close();
                counter = counter + 1;
            }
            ss.close();
        } catch(Exception e) {
            System.out.println(e);
        }
    }
}

class testobject implements Serializable {
    int value;
    String id;
    String field1;
    String field2;
    String field3;
    String field4;
    public testobject(int v, String s, String s1, String s2, String s3, String s4) {
        this.value=v;
        this.id=s;
        this.field1 = s1;
        this.field2 = s2;
        this.field3 = s3;
        this.field4 = s4;
    }
}

【问题讨论】:

  • 您应该改进这种格式。没有人会读到!
  • 抱歉剪切/粘贴错误愚蠢地没有检查。
  • 不要在同一个套接字上不断创建新的ObjectInputStreamsObjectOutputStreams。在插座的整个生命周期中使用相同的;并首先创建ObjectOutputStream

标签: java sockets tcp


【解决方案1】:

代码中的 EOFException

问题似乎出在您的while (to.value != 1) 上。服务器接收到第一个对象,值为 1。它根本不执行该 while 循环,而是立即关闭套接字。因此,当客户端尝试从该套接字的输入流创建ObjectInputStream 时,它会遇到一个关闭的连接,它会在该连接处期望一个对象流标头。因此EOFException

实施对话

实现对话的最简单方法是完全避免循环。毕竟,您执行循环,然后在循环中进行大小写区分以在每次传递中执行特殊代码。您不妨编写一个线性程序,并在需要时将通用代码分解为方法调用,尽管您的示例几乎没有通用代码。

class SimpleClient {
    public static void main(String args[]) throws Exception {

        // Connection setup
        Socket s = new Socket("localhost",2002);
        OutputStream os = s.getOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);
        InputStream is = s.getInputStream();
        ObjectInputStream ois = new ObjectInputStream(is);
        testobject to;

        // Conversation

        System.out.println("sending object 1");
        to = new testobject(1,"object 1","field1","field2","field3","field4");
        oos.writeObject(to);

        System.out.println("receiving object 2");
        to = (testobject)ois.readObject();
        System.out.println(to.id);

        System.out.println("sending object 3");
        to = new testobject(2,"object 3","field1","field2","field3","field4");
        oos.writeObject(to);

        System.out.println("receiving object 4");
        to = (testobject)ois.readObject();
        System.out.println(to.id);

        // Connection shutdown
        ois.close();
        oos.close();
        s.close();
    }
}

class SimpleServer {
    public static void main(String args[]) throws Exception {

        // Connection setup
        ServerSocket ss = new ServerSocket(2002);
        Socket s = ss.accept(); // only handle a single connection
        ss.close(); // so we can immediately stop listening for more
        OutputStream os = s.getOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);
        InputStream is = s.getInputStream();
        ObjectInputStream ois = new ObjectInputStream(is);
        testobject to;

        // Conversation

        System.out.println("receiving object 1");
        to = (testobject)ois.readObject();
        System.out.println(to.id);

        System.out.println("sending object 2");
        to = new testobject(2,"object 2","field1","field2","field3","field4");
        oos.writeObject(to);

        System.out.println("receiving object 3");
        to = (testobject)ois.readObject();
        System.out.println(to.id);

        System.out.println("sending object 4");
        to = new testobject(4,"object 4","field1","field2","field3","field4");
        oos.writeObject(to);

        // Connection shutdown
        ois.close();
        oos.close();
        s.close();
    }
}

发送和接收队列

如果你真的想从队列中发送东西,你可以简单地遍历它。

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

class SimpleClient {
    public static void main(String args[]) throws Exception {

        // Preparing the queues
        List<testobject> sendQueue = Arrays.asList(
            new testobject(1,"object 1","field1","field2","field3","field4"),
            new testobject(2,"object 3","field1","field2","field3","field4"));
        List<testobject> receiveQueue = new ArrayList<testobject>();

        // Connection setup
        Socket s = new Socket("localhost",2002);
        OutputStream os = s.getOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);
        InputStream is = s.getInputStream();
        ObjectInputStream ois = new ObjectInputStream(is);
        testobject to;

        // Conversation, we start by sending
        for (testobject toSend: sendQueue) {
            System.out.println("Sending " + toSend.id);
            oos.writeObject(toSend);
            testobject received = (testobject)ois.readObject();
            System.out.println("Received " + received.id);
            receiveQueue.add(received);
        }

        // Connection shutdown
        ois.close();
        oos.close();
        s.close();
    }
}

class SimpleServer {
    public static void main(String args[]) throws Exception {

        // Preparing the queues
        List<testobject> sendQueue = Arrays.asList(
            new testobject(2,"object 2","field1","field2","field3","field4"),
            new testobject(4,"object 4","field1","field2","field3","field4"));
        List<testobject> receiveQueue = new ArrayList<testobject>();

        // Connection setup
        ServerSocket ss = new ServerSocket(2002);
        Socket s = ss.accept(); // only handle a single connection
        ss.close(); // so we can immediately stop listening for more
        OutputStream os = s.getOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);
        InputStream is = s.getInputStream();
        ObjectInputStream ois = new ObjectInputStream(is);
        testobject to;

        // Conversation, we start by receiving
        for (testobject toSend: sendQueue) {
            testobject received = (testobject)ois.readObject();
            System.out.println("Received " + received.id);
            receiveQueue.add(received);
            System.out.println("Sending " + toSend.id);
            oos.writeObject(toSend);
        }

        // Connection shutdown
        ois.close();
        oos.close();
        s.close();
    }
}

但是由于在这种情况下,所有数据都是预先知道的,您可以通过不交错来节省一些网络往返行程,而是立即在两端发送所有数据,使用单独的线程来接收内容。但是,这与您的示例相距甚远,因此我不会包含此代码。

【讨论】:

  • 这是EOF错误的答案。谢谢你。如何按顺序从堆栈或队列发送/接收对象?
  • @Matt1993:我想我不完全理解你在这方面的问题。使用堆栈和队列,我将关联一系列对象,因此您可以简单地遍历它们。另一方面,您的示例似乎表明某种形式的对话,其中发送的消息取决于之前收到的消息。我将在我的帖子中包含这两个问题的答案。
  • 谢谢 MvG,这两个答案都会有所帮助,但作为参考,我想做的是模拟 TCP 握手协议。客户端以 client_hello 启动,服务器以 server_hello 响应,每个对象(例如 server_hello)包含字段(2-3 个字符串)。
猜你喜欢
  • 1970-01-01
  • 2013-02-07
  • 2014-01-11
  • 2021-01-11
  • 2015-08-31
  • 2012-08-29
  • 1970-01-01
  • 2023-04-03
  • 2011-06-21
相关资源
最近更新 更多