通过TCP / IP接收对象

时间:2014-01-12 09:13:04

标签: java sockets tcp-ip objectinputstream

我将通过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();}
    }

我收到一个例外:

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)

它指的是这一行:

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

这是我的服务器代码:

            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();

客户端代码:

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!");
            }

任何人都可以解释我发生了什么,这个例外是什么以及为什么我收到这个例外?

3 个答案:

答案 0 :(得分:5)

如果您想通过网络发送对象,则必须序列化您的对象。

检查此问题: How To send an object over TCP in Java

Java序列化: Serialization

你可以这样做:

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);}  
  }  
}  

答案 1 :(得分:3)

摆脱发送和接收布尔值。这是多余的。如果创建连接时出现问题,则不会创建套接字:将抛出异常。您在同一个套接字上混淆了多个流的所有内容。不要那样做。

在read-object循环中,你需要单独捕获EOFException,当你得到它时,关闭套接字并退出循环。如果您收到任何其他IOException,请记录它,关闭套接字,然后退出循环。

答案 2 :(得分:1)

如果您希望获得良好的性能并发送对象,那么您绝对应该使用Google Protobuf

它允许您在简单的.proto文件中定义消息。然后使用捆绑的编译器生成将被序列化并发送的Java类。

更好的想法是使用Netty而不是普通的Java套接字。这可以防止您编写大量样板代码并定义简单的序列化/反序列化管道。看看user-guide