Java Streams-ObjectOutputStream提供空值
我有两个应用程序可以相互配合使用。一种是“服务器”类型的应用程序,它没有任何GUI界面,处理对数据库的查询并处理来自客户端的请求。另一个是“客户机”,它主要是一个GUI,供用户以结构化方式与数据库信息交互 需要的问题/麻烦/帮助 我遇到的问题是,我可以成功地将一个对象(字符串[])发送到服务器,并且没有任何问题。客户端应用程序发送,服务器应用程序接收并成功处理 如果我尝试发送第二个字符串[],客户端编译数组并认为它已被发送,但服务器从未收到is(仅获取null)并生成IOException 甚至对于包含完全相同数量的位置和完全相同格式和位置的完全相同文本的数组也是如此 printStackTrace()产生的错误是: 第204行的代码是从中读取ObjectStream的点:Java Streams-ObjectOutputStream提供空值,java,ioexception,objectoutputstream,objectinputstream,Java,Ioexception,Objectoutputstream,Objectinputstream,我有两个应用程序可以相互配合使用。一种是“服务器”类型的应用程序,它没有任何GUI界面,处理对数据库的查询并处理来自客户端的请求。另一个是“客户机”,它主要是一个GUI,供用户以结构化方式与数据库信息交互 需要的问题/麻烦/帮助 我遇到的问题是,我可以成功地将一个对象(字符串[])发送到服务器,并且没有任何问题。客户端应用程序发送,服务器应用程序接收并成功处理 如果我尝试发送第二个字符串[],客户端编译数组并认为它已被发送,但服务器从未收到is(仅获取null)并生成IOException 甚至
String[] addArray = (String[]) ois.readObject();
ois是ObjectInputStream,初始化如下:
private ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
客户端代码
用于将这些对象发送到服务器应用程序的客户端代码为:
ObjectToServer.writeObject(String[] var);
ObjectToServer.flush();
ObjectToServer.reset();
评论
对我来说没有意义的是,使用完全相同的代码格式通过objectOutputStream成功地将大量字符串[]从服务器发送到客户端应用程序,而从不发送“null”
我在谷歌上搜索了这一切,但都毫无用处
如果可以的话,请找个人帮忙
ADDITIONAL CODE
// CONNECTION THREAD IS ON SERVER APP, SETS UP STREAMS AND WAITS FOR MESSAGES FROM CLIENT
// HANDLES COMMUNICATION FROM CLIENT AND REST OF SERVER
public class ConnectionThread implements Runnable
{
private Socket socket;
private SystemCore core;
//Streams for connections
private InputStream is;
private OutputStream os;
//Writers and readers for communication of Strings
private PrintWriter toClient;
private BufferedReader fromClient;
// Writers and readers for sending and receiving Objects between server and client.
private ObjectInputStream ois = null;
private ObjectOutputStream oos = null;
//Protocol
static final String CLIENT_QUITTING = "Exit";
public ConnectionThread(Socket s, SystemCore aSysCore)
{
socket = s;
// State of the SystemCore as taken from HelloServer
core = aSysCore;
}
public void run()
{
try
{
openStreams();
toClient.println(MESSAGE_TO_CLIENT);
processClientRequests();
closeStreams();
this.socket.close();
}
catch (OptionalDataException ode )
{
System.out.println("OptionalDataException: ");
System.out.println("length is: " + ode.length);
}
catch (IOException ioe)
{
System.out.println("IO trouble with a connection in ConnectionThread run() " + ioe.getMessage());
ioe.printStackTrace();
}
catch (ClassNotFoundException cnf)
{
System.out.println("Class trouble with a connection in ConnectionThread run() " + cnf.getMessage());
cnf.printStackTrace();
}
catch(ParseException pe)
{
System.out.println("Parse trouble with a connection in ConnectionThread run() " + pe.getMessage());
pe.printStackTrace();
}
}
/**
* Opens streams between the server and the client.
*
* @throws IOException
*/
private void openStreams() throws IOException
{
final boolean AUTO_FLUSH = true;
this.is = this.socket.getInputStream();
this.fromClient = new BufferedReader(new InputStreamReader(is));
this.os = this.socket.getOutputStream();
this.toClient = new PrintWriter(os, AUTO_FLUSH);
//Object streams.
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
System.out.println("...Streams set up");
}
/**
* Private method that accepts arguments from a client and executes the related
* commands in the systemcore as long as the command passed from the client
* is not CLIENT_QUITTING.
*
* @throws IOException
* @throws ClassNotFoundException
*/
private void processClientRequests() throws IOException, ClassNotFoundException, ParseException
{
String commandFromClient;
commandFromClient = fromClient.readLine();
while (!(commandFromClient.equals(CLIENT_QUITTING)))
{
if (commandFromClient.equals("addProjectPrepare"))
{
String[] addArray = (String[]) ois.readObject();
core.addProjectPrepare(addArray);
}
if (commandFromClient.equals("editProjectPrepareDetails"))
{
String[] editArray = (String[]) ois.readObject();
recruit.editProjectPrepareDetails(editArray);
}
}
commandFromClient = fromClient.readLine();
}
**// CLIENT SIDE (User GUI) CODE THAT SENDS STRING[] TO THE SERVER**
public void saveAction()
{
// TEST TO SEE IF THE DATE ENTERED IS CORRECT FORMAT, IF NOT NO SAVE OCCURRS
boolean parsedOk = false;
if (this.arrivalDateTextField.getText().isEmpty() == false)
{
try
{
// Check if date is correct format. Nothing will be done with
// the testDate object
MyDate testDate = new MyDate(
this.arrivalDateTextField.getText());
//Allow write to server to occur.
parsedOk = true;
//If date is okay, send form data to server.
}
catch (ParseException pe)
{
this.arrivalDateTextField.setText(""); // Set text field to blank
int messageIcon = javax.swing.JOptionPane.ERROR_MESSAGE;
JOptionPane.showMessageDialog(this, "Invalid date",
"Warning", messageIcon);
}
}
else
{
parsedOk = true; // No date entered so allow blank.
}
if (parsedOk == true)
{
// WRITE DATA TO SERVER OCCURS HERE:
try
{
**//getPersonDetails() returns a String[]**
ManageClientConnections.toServer.println("addNewData");
ManageClientConnections.objectToServer.writeObject(this.getPersonDetails());
ManageClientConnections.objectToServer.flush();
ManageClientConnections.objectToServer.reset();
}
catch (IOException ioe)
{
System.out.println(
"While writing new person to server, there was an error: " + ioe.getMessage());
}
// And dispose of the GUI, inside the parseok if clause
this.dispose();
}
}
不能在同一套接字输入/输出流上创建多个输入/输出流。那不行。你需要选择一种类型的流并坚持下去。由于需要发送结构化数据,因此应仅使用对象流,而不使用打印流。如果您需要从客户端发送不同类型的消息到服务器,那么您应该考虑使用包可序列化对象类型(例如消息),它可以包含不同类型的消息。您可以捕获<代码> OptoDATA异常> /代码>并打印<代码>异常吗?长度< /代码>字段,请?还有,上面的注释。为什么要重置输出流?感谢Pescis和jtahlborn-我添加了适用的附加代码@Pecsis-在OptionalDataException的exception.length上,长度为0。Fildor-我重置了输出流,因为我有一个打开的流,并且一遍又一遍地向它写入对象。根据我刚才读到的内容,我需要重置ObjectOutputStream,否则会出现连续错误。“服务器从不接收is(仅获取null)并生成IOException。”否。它会抛出一个
IOException
,而不是生成任何内容。任何空值都是由您的代码生成的。@Fildor如果您不知道ObjectOutputStream.reset()
的作用,请查找它。OP在这里做的事情并不奇怪,但它是一个流,其中写入了多个对象,然后刷新和重置,而不是多个流。将多个对象从服务器应用程序写入到客户端应用程序的单个流中确实有效。@joelBeaton-huh?您的openStreams
方法在同一套接字InputStream上创建一个BufferedReader和ObjectInputStream。确实,其中一个(BufferedReader)处理客户端应用程序中PrintWriter写入的字符串,而另一个(ObjectInputStream)处理来自客户端的传入对象。这是不允许的吗?我是否应该创建两个套接字对象并将此通信量拆分?@joelBeaton-回答了我答案中已经存在的所有问题。好的,我将调整所有这些,然后回到这里,让您知道它是如何进行的。
ADDITIONAL CODE
// CONNECTION THREAD IS ON SERVER APP, SETS UP STREAMS AND WAITS FOR MESSAGES FROM CLIENT
// HANDLES COMMUNICATION FROM CLIENT AND REST OF SERVER
public class ConnectionThread implements Runnable
{
private Socket socket;
private SystemCore core;
//Streams for connections
private InputStream is;
private OutputStream os;
//Writers and readers for communication of Strings
private PrintWriter toClient;
private BufferedReader fromClient;
// Writers and readers for sending and receiving Objects between server and client.
private ObjectInputStream ois = null;
private ObjectOutputStream oos = null;
//Protocol
static final String CLIENT_QUITTING = "Exit";
public ConnectionThread(Socket s, SystemCore aSysCore)
{
socket = s;
// State of the SystemCore as taken from HelloServer
core = aSysCore;
}
public void run()
{
try
{
openStreams();
toClient.println(MESSAGE_TO_CLIENT);
processClientRequests();
closeStreams();
this.socket.close();
}
catch (OptionalDataException ode )
{
System.out.println("OptionalDataException: ");
System.out.println("length is: " + ode.length);
}
catch (IOException ioe)
{
System.out.println("IO trouble with a connection in ConnectionThread run() " + ioe.getMessage());
ioe.printStackTrace();
}
catch (ClassNotFoundException cnf)
{
System.out.println("Class trouble with a connection in ConnectionThread run() " + cnf.getMessage());
cnf.printStackTrace();
}
catch(ParseException pe)
{
System.out.println("Parse trouble with a connection in ConnectionThread run() " + pe.getMessage());
pe.printStackTrace();
}
}
/**
* Opens streams between the server and the client.
*
* @throws IOException
*/
private void openStreams() throws IOException
{
final boolean AUTO_FLUSH = true;
this.is = this.socket.getInputStream();
this.fromClient = new BufferedReader(new InputStreamReader(is));
this.os = this.socket.getOutputStream();
this.toClient = new PrintWriter(os, AUTO_FLUSH);
//Object streams.
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
System.out.println("...Streams set up");
}
/**
* Private method that accepts arguments from a client and executes the related
* commands in the systemcore as long as the command passed from the client
* is not CLIENT_QUITTING.
*
* @throws IOException
* @throws ClassNotFoundException
*/
private void processClientRequests() throws IOException, ClassNotFoundException, ParseException
{
String commandFromClient;
commandFromClient = fromClient.readLine();
while (!(commandFromClient.equals(CLIENT_QUITTING)))
{
if (commandFromClient.equals("addProjectPrepare"))
{
String[] addArray = (String[]) ois.readObject();
core.addProjectPrepare(addArray);
}
if (commandFromClient.equals("editProjectPrepareDetails"))
{
String[] editArray = (String[]) ois.readObject();
recruit.editProjectPrepareDetails(editArray);
}
}
commandFromClient = fromClient.readLine();
}
**// CLIENT SIDE (User GUI) CODE THAT SENDS STRING[] TO THE SERVER**
public void saveAction()
{
// TEST TO SEE IF THE DATE ENTERED IS CORRECT FORMAT, IF NOT NO SAVE OCCURRS
boolean parsedOk = false;
if (this.arrivalDateTextField.getText().isEmpty() == false)
{
try
{
// Check if date is correct format. Nothing will be done with
// the testDate object
MyDate testDate = new MyDate(
this.arrivalDateTextField.getText());
//Allow write to server to occur.
parsedOk = true;
//If date is okay, send form data to server.
}
catch (ParseException pe)
{
this.arrivalDateTextField.setText(""); // Set text field to blank
int messageIcon = javax.swing.JOptionPane.ERROR_MESSAGE;
JOptionPane.showMessageDialog(this, "Invalid date",
"Warning", messageIcon);
}
}
else
{
parsedOk = true; // No date entered so allow blank.
}
if (parsedOk == true)
{
// WRITE DATA TO SERVER OCCURS HERE:
try
{
**//getPersonDetails() returns a String[]**
ManageClientConnections.toServer.println("addNewData");
ManageClientConnections.objectToServer.writeObject(this.getPersonDetails());
ManageClientConnections.objectToServer.flush();
ManageClientConnections.objectToServer.reset();
}
catch (IOException ioe)
{
System.out.println(
"While writing new person to server, there was an error: " + ioe.getMessage());
}
// And dispose of the GUI, inside the parseok if clause
this.dispose();
}
}