简体   繁体   English

通过TCP / IP接收对象

[英]Receive an object over TCP/IP

I am going to write a program over TCP/IP and I should send objects by client or by server, It is going right when I want to send or receive strings but when I am trying to read an object: 我将通过TCP / IP编写一个程序,我应该通过客户端或服务器发送对象,当我想发送或接收字符串但是当我试图读取一个对象时,它是正确的:

private Socket client;

public ThreadedClient(Socket client) {
    this.client = client;
}

@Override
public void run() {
        try {
            ObjectInputStream objIn = new ObjectInputStream(client.getInputStream());
            while(true){
                try {
                    Object fromClient = objIn.readObject();

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

I receive an exception: 我收到一个例外:

java.io.StreamCorruptedException: invalid stream header: 306E6165
    at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
    at java.io.ObjectInputStream.<init>(Unknown Source)
    at org.bihe.serverSocket.ThreadedClient.run(Server.java:137)
    at java.lang.Thread.run(Unknown Source)

and it refers to this line: 它指的是这一行:

    ObjectInputStream objIn = new ObjectInputStream(client.getInputStream());

It is my server code: 这是我的服务器代码:

            ServerSocket ss = new ServerSocket(8800);
            while(true){
                Socket newClient = ss.accept();

                System.out.println(">>>> Client number " + (++counter) + " connected.");
                OutputStream outputStream = newClient.getOutputStream();
                PrintWriter sender = new PrintWriter(outputStream);
                sender.println(true);
                sender.flush();
                ThreadedClient client = new ThreadedClient(newClient);
                clients.add(client);
                new Thread(client).start();

Client side code: 客户端代码:

sc = new Socket("127.0.0.1", 8800);
            InputStream inputStream = sc.getInputStream();
            Scanner scanner = new Scanner(inputStream);
            boolean s = scanner.nextBoolean();
            if(s){
                System.out.println("Client connected successfully.");
                return true;
            }else{
                System.out.println("Ohhh, Some problem happened, try again later!");
            }

Can anyone explain me what is happening, what is this exception and why I received this exception? 任何人都可以解释我发生了什么,这个例外是什么以及为什么我收到这个例外?

If you want to send object over network you must serialize your objects. 如果要通过网络发送对象,则必须序列化对象。

Check this question: How To send an object over TCP in Java 检查这个问题: 如何通过TCP在TCP上发送对象

Java Serialization: Serialization Java序列化: 序列化

You could do it like this: 你可以这样做:

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

class testobject implements Serializable {  
  int value;  
  String id;  

  public  testobject(int v, String s ){  
       this.value=v;  
       this.id=s;  
    }  

}  

public class SimpleServer  {  
  public static void main(String args[]) {  
  int port = 2002;  
  try {  
    ServerSocket ss = new ServerSocket(port);  
    Socket s = ss.accept();  
    InputStream is = s.getInputStream();  
    ObjectInputStream ois = new ObjectInputStream(is);  
    testobject to = (testobject)ois.readObject();  
    if (to!=null){System.out.println(to.id);}  
    System.out.println((String)ois.readObject());  
    is.close();  
    s.close();  
    ss.close();  
}catch(Exception e){System.out.println(e);}  
}  
}  

import java.net.*;  
import java.io.*;  
   public class SimpleClient {  
   public static void main(String args[]){  
     try{  
     Socket s = new Socket("localhost",2002);  
     OutputStream os = s.getOutputStream();  
     ObjectOutputStream oos = new ObjectOutputStream(os);  
     testobject to = new testobject(1,"object from client");  
     oos.writeObject(to);  
     oos.writeObject(new String("another object from the client"));  
     oos.close();  
     os.close();  
     s.close();  
   }catch(Exception e){System.out.println(e);}  
  }  
}  

Just get rid of sending and receiving the Boolean. 只是摆脱发送和接收布尔值。 It's redundant. 这是多余的。 If there was some problem creating the connection, the socket wouldn't get created: an exception would be thrown instead. 如果创建连接时出现问题,则不会创建套接字:将抛出异常。 You're confusing everything with multiple streams on the same socket. 您在同一个套接字上混淆了多个流的所有内容。 Don't do that. 不要那样做。

In your read-object loop, you need to catch EOFException separately, and when you get it, close the socket and exit the loop. 在read-object循环中,你需要单独捕获EOFException,当你得到它时,关闭套接字并退出循环。 If you get any other IOException, log it, close the socket, and exit the loop. 如果您收到任何其他IOException,请记录它,关闭套接字,然后退出循环。

If you'd like to achieve good performance and send object then you definitely should use Google Protobuf 如果您想获得良好的性能并发送对象,那么您肯定应该使用Google Protobuf

It allows you to define messages in simple .proto files. 它允许您在简单的.proto文件中定义消息。 Then you use bundled compiler to generate Java classes which will be serialized and sent. 然后使用捆绑的编译器生成将被序列化和发送的Java类。

Also better idea is to use Netty over plain Java sockets. 更好的想法是使用Netty而不是普通的Java套接字。 This prevent you from writing a lot of boilerplate code and define simple serialization/deserialization pipelines. 这可以防止您编写大量样板代码并定义简单的序列化/反序列化管道。 Take a look at user-guide . 看一看用户指南

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM