【问题标题】:Exchanging object with sockets用套接字交换对象
【发布时间】:2015-06-17 22:25:51
【问题描述】:

我正在尝试使用套接字在 Java 中编写客户端和服务器之间的简单交互。

服务器

public class MyServer
{
  private static final int SPORT = 4444;
  ServerSocket server;
  Socket client;
  ObjectInputStream is;
  ObjectOutputStream os;


  /**
   * Constructor
   */
  public MyServer() {
    try
    {
      server = new ServerSocket(SPORT);
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }

    listenAndReply();
  }


  public void listenAndReply()
  {
    System.out.println("Server running.");
    System.out.println("Waiting for connection...");
    try
    {
      client = server.accept();

      System.out.println("Connection accepted. \n");

      is = new ObjectInputStream(client.getInputStream());
      os = new ObjectOutputStream(client.getOutputStream());

      while(! client.isClosed()) {

        Object o = is.readObject();

        // ... process object ...

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


  public void sendCommand(Command c) {
    try
    {
      os.reset();
      os.writeObject(c);
      os.flush();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

客户

public class MyClient implements ChatClient
{
  private static final int SPORT    = 4444;
  private static final String SHOST = "127.0.0.1";
  Socket socket;
  ObjectInputStream is = null;
  ObjectOutputStream os = null;


  public MyClient() {
    try
    {
      socket = new Socket(SHOST, SPORT);
      os = new ObjectOutputStream(socket.getOutputStream());
      is = new ObjectInputStream(socket.getInputStream());
      System.out.println("Client socket created.");
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }


  @Override
  public Command receive()
  {
    try
    {
      Object o = is.readObject();

      if(o instanceof Command) {
        System.out.println("Received command: " + o.getClass().getSimpleName());
        return (Command) o;
      }
    }
    catch (IOException | ClassNotFoundException e)
    {
      e.printStackTrace();
    }

    return null;
  }


public void sendCommand(Command c) {
    System.out.println("Client sending command " + c.getClass().getSimpleName());

    try
    {
      os.reset();
      os.writeObject(c);
      os.flush();
      System.out.println("Command sent. \n");
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

}

你能看出哪里不对吗?问题是,如果我尝试交换多个对象,我会得到

java.io.StreamCorruptedException:无效类型代码:00

编辑 - 已解决

最后我设法解决了这个问题:正如 Pshemo 所怀疑的那样,问题不在这段代码中,而是在另一个类中,那里有另一个对接收方法的调用,这显然导致了奇怪的行为。现在我将不得不重新考虑一下结构,但至少套接字通信看起来不错。

【问题讨论】:

  • os.reset();sendCommand 中的作用是什么?
  • 它应该重置流以使其看起来像一个新打开的流,正如我在另一个问题中所读到的。无论如何,忽略它并不会改变结果。
  • 我无法重现您的错误。您可以创建并发布SSCCE(简短但完整的代码可以重现您的问题)吗?
  • 其实这只是一个更大项目的一小部分。我以为我只是在对象流上犯了一些愚蠢的错误,所以我试图削减其他所有内容,只发布与对象交换相关的代码
  • 是的,我意识到,但是创建 SSCCE 有很多优点:(1) 它可以帮助您缩小问题范围 (2) 这使得回答更容易 (3) 它可以帮助未来的读者更容易地测试他们是否面临类似的问题问题。所以我建议无论如何都要创建它,因为第 1 点(我在创建 SSCCE 时经常在我的代码中发现问题,所以真的值得花相当多的时间来创建它)。

标签: java sockets serialization


【解决方案1】:

在服务器类中,您尝试从客户端获取输入和输出,但在客户端类中,您将游览客户端套接字设置为套接字而不是客户端。你试图通过一个类而不是一个套接字来获取信息,所以我猜这是你的问题。如果我错了,请纠正我

public class MyServer{

private static final int SPORT = 4444;



/**
* Constructor
*/
public MyServer() {
try
{
  ServerSocket server = new ServerSocket(SPORT);
}
catch (IOException e)
{
  e.printStackTrace();
}

listenAndReply();
}


public void listenAndReply(){

System.out.println("Server running.");
System.out.println("Waiting for connection...");
try
{
  socket = server.accept();

  System.out.println("Connection accepted. \n");

  InputStream is = new InputStream(socket.getInputStream()); //changed from client.getInputStream() because in your client class you have setup your client socket to be named socket instead of client.
  OutputStream os = new OutputStream(socket.getOutputStream()); //changed from client.getOutputStream() since your client class has a differently named client socket, your server can’t get information from it by calling client.get

  while( !socket.isClosed()) {

    Object o = is.readObject();

    // ... process object ...

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

}

【讨论】:

  • '...但是在您的客户端类中,您将游览客户端套接字设置为套接字而不是客户端'是什么意思?谢谢
  • 在您的客户端类中,您将客户端套接字设置为套接字套接字 = 新套接字,但在您的服务器类中,您的输入和输出流来自 client.get.. 见。您试图从您的客户端中未实例化的套接字名称中提取
  • 哦,是的,只是一个错字...无论如何我还是不明白:在服务器类中,客户端被声明为 Socket 对象,而在客户端类中我尝试连接到服务器通过名为 'socket' 的 Socket 对象。我是否遗漏了您的回答?
  • 没错,您的服务器正在寻找 client.getinput 和 output 而它应该寻找 socket.getinput/output 因为这是您设置客户端的方式
  • socket 不是服务器类的成员,那么应该如何找到它呢?套接字的名称是“客户端”,这是我用来获取流的名称。无论如何,我按照你说的尝试了,但我显然得到了“套接字无法解析”。
猜你喜欢
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 2021-08-04
  • 2013-06-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多