as the title says, getting the error "outputsteam is abstract". I'm new to Java so not quite sure how to go about solving it. My program is trying to send an arraylist of connections over a socket to a client, using this code;
public void sendList(Socket clientSocket, ArrayList connections) throws IOException
{
OutputStream outputStream = new OutputStream(clientSocket.getOutputStream(), true);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(connections);
System.out.println("List sent");
}
Thanks in advance!
The error message is telling you exactly what is wrong: You can't call a constructor on an abstract class, and instead will have to initiate one of the concrete subclasses of OutputStream. Perhaps a BufferedOutputStream that wraps your clientSocket OutputStream.
Why do you even have this line?
OutputStream outputStream = new OutputStream(clientSocket.getOutputStream(),
true);
Why not simply use directly use the OutputStream from the clientSocket?
Related
I have a Socket with its input ad output stream. I want to use output synchronously and input asynchronously and store everything received without blocking the input.
Socket socket;
BufferedOutputStream outToServer;
DataInputStream inFromServer;
List<byte[]> incoming=ArrayList<byte[]>();
socket = new Socket();
socket.connect(new InetSocketAddress("127.0.0.1",9100), 5000);
outToServer = new BufferedOutputStream(socket.getOutputStream());
inFromServer = new DataInputStream(socket.getInputStream());
How can I add an input listener to fill incoming list with incoming data?
Basically you want to look into the java.nio packages. There is full support for doing "async", "non-blocking IO" with standard java ... since quite some years.
See here for some examples. That tutorial basically starts with code as you have written in your question ... to transform that into "async".
But to be precise: you don't need to use "nio" or "nio2"; but if you are serious about turning into that direction, then nio/nio2 provide extremely helpful features.
There is no way to read InputStream asynchronously. You have to go where this InputStream is created, and access the source of data explicetly.
You need only to pass the InputStream to the Runnable that need to be executed asynchronously. This can be done for example in the constructor.
public class ConsumeInput implements Runnable {
private InputStream inputStream;
public ConsumInput(InputStream inputStream) {
this.inputStream = inputStream;
}
public void run() {
// Do something with inputStream
}
}
And in the main thread
...
ConsumeInput consumeInput = new ConsumeInput(inFromServer);
Thread t = new Thread(consumeInput);
t.start();
Obviously you can also use the new api to handle threads.
Note: this is only a skeleton code. You need to handle exceptions and closure of streams.
Here is the situation:
I have a ServerSocket ss, and "Socket socket = ss.accept();", then if I do this:
istream = socket.getInputStream();
ostream = socket.getOutputStream();
in = new BufferedReader(new InputStreamReader(istream));
out = new PrintWriter(new BufferedOutputStream(ostream));
/*
I use in/out few times
everything OK
*/
ObjectOutputStream oos = new ObjectOutputStream(ostream);
oos.writeObject(someobject);
/* probably code that solves the problem */
String line = in.readLine();
On the client side I have this code:
PrintWriter out = new PrintWriter(new BufferedOutputStream(socket.getOutputStream()),true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
/*
using in/out, no problems
*/
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
SomeObject so = (SomeObject)ois.readObject();
out.println("some text");
Everything is OK, until I send someobject. Client recieves object properly, no problems there. But I can't use socket anymore. If I do oos.close(), I get Exception that says "socket closed". If I do oos.reset() I get Exception with similar message. "socket reset". So what should I do? Is it possible to use same input and output streams after writeObject()?
What happens when I send "some text" is that I'm just getting nulls no matter how many times I call readLine(), I never get that "some text".
You can't use multiple type of stream/reader/writer on the same underlying socket. All your streams and readers and writers are buffered so they will all get thoroughly mixed up. Stick tone kind. Stick to one protocol. If you have object streams, use them for everything. And create them once for the life of the socket, not per message.
I've serialized some objects so I can convert them to byte arrays for a TCP packet. When I send the objects from the server program to the client program, there are no issues and it works fine. However, even though the code between the server and client is identical, when I try to send objects from the client to the server I get an invalid header.
Here are the objects I'm serializing:
public static byte[] serialize(Hand c) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(c);
return baos.toByteArray();
}
public static Hand deserialize(byte[] bytes) throws IOException, ClassNotFoundException
{
ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream o = new ObjectInputStream(b);
return (Hand) o.readObject();
}
and
public static byte[] serialize(Card c) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(c);
return baos.toByteArray();
}
public static Card deserialize(byte[] bytes) throws IOException, ClassNotFoundException
{
ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream o = new ObjectInputStream(b);
return (Card) o.readObject();
}
Those are both taken from the Server program, but the code for the serialization is identical between the server and the client; I important the Card class and the Hand class from the Server to the Client precisely to make sure errors like this wouldn't occur.
The server can convert a Card or a Hand to a byte[] and write it over a DataOutputStream to the client, and the client can receive the Card or Hand through a DataInputStream, deserialize it, and read it with no problem. When I try to send a Card or a Hand from the Client to the Server, however, very rarely it works and usually I get a
Exception in thread "main" java.io.StreamCorruptedException: invalid stream header: 434B0005
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at Hand.deserialize(Hand.java:29)
at KoiKoi_TCP_Server.takeClientTurn(KoiKoi_TCP_Server.java:321)
at KoiKoi_TCP_Server.main(KoiKoi_TCP_Server.java:380)
where Hand.java.29 points at the line
ObjectInputStream o = new ObjectInputStream(b);
in the Hand deserialization method.
I understand that it's telling me that the header is invalid. I'm not sure how to fix it, because it only breaks going one direction and the code is identical. Suggestions?
I'm only sending a solitary object at a time, so I'm not initializing multiple ObjectInputStreams or anything.
I'm not initializing multiple ObjectOutputStreams or anything.
Yes you are. You are initializing a new ObjectOutputStream for every object, and then you're giving yourself the additional problem of knowing how many bytes to read in order to receive each object, and you're getting that wrong, so you're getting out of sync.
Get rid of all this. You don't need it. It is just adding problems. Just use a single ObjectOutputStream and ObjectInputStream, directly, for the life of the socket, constructed directly over the socket streams, and call writeObject() when you want to send an object, and readObject() when you want to read one. Two lines of code. Forget about the byte arrays and the ByteArray/DataInput/OutputStreams altogether.
I have server and client set up, which is basically a basic text email system. I am currently using a PrintWriter to send the text between the server and client. I am trying to create a attachment based system and to do this I am using a ObjectOutputStream.
private static PrintWriter output;
private static ObjectOutputStream outStream;
public ClientHandler(Socket socket) throws IOException
{
client = socket;
outStream = new ObjectOutputStream(client.getOutputStream());
input = new Scanner(client.getInputStream());
output = new PrintWriter(client.getOutputStream(), true);
}
I currently have the problem where if I try send text via the output printwriter, for some reason extra characters will be added to the beginning of the text that is sent, meaning the program cannot identify key words being passed via the printwriter to the client. The problem will stop if i comment out the creation of the outStream object.
Can anyone give me any advice to try solve this problem of conflict?
This extra text is coming from the object output stream.
Attaching an ObjectOutputStream AND a PrintStream to the same outputstream is basically just never going to work. You have to come up with a solution for using 1 or the other. To use just a PrintStream, you might consider converting your object(s) to JSON or XML. On the other hand, you could just use an ObjectOutputStream and write your strings to the ObjectOutputStream
ObjectOutputStream should only be used as an ObjectOutputStream on that channel. Use the PrintWriter on another socket if you really need it.
Extend your ClientHandler and overwrite the constructor to include code for handling file transfers. Have two ports open, one for text and another for file transfers.
private static PrintWriter output;
public ClientHandler(Socket socket) throws IOException
{
client = socket;
input = new Scanner(client.getInputStream());
output = new PrintWriter(client.getOutputStream(), true);
}
private static ObjectOutputStream outStream;
public ClientFileHandler(Socket socket) extends ClientHandler throws IOException
{
client = socket;
outStream = new ObjectOutputStream(client.getOutputStream());
}
I'm doing some socket programming in Java and I'd like to be able to change between using the ObjectOutputStream, the DataOutputStream, and the PrintWriter all within the same socket/connection. Is this possible and what is the best way to do it?
I've tried just creating both types of objects, for example ObjectOutputStream and DataOutputStream, but that doesn't seem to work.
The reason I want to switch between them is to, for example, send a text command "INFO" that signals I'm about to send an object with information or a command "DATA" signalling that I'm about to send data. Any advice on the best way to do this is appreciated.
You can only use one underlying stream type however you can get that data from anywhere.
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));
public static void writeObject(DataOutputStream dos, Serializable obj) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
dos.writeUTF("OBJECT");
byte[] bytes = baos.toByteArray();
dos.writeInt(bytes.length);
dos.write(bytes);
dos.flush();
}
public static void writeBytes(DataOutputStream dos, byte[] bytes) {
dos.writeUTF("BYTES");
dos.writeInt(bytes.length);
dos.write(bytes);
dos.flush();
}
public static void writeText(DataOutputStream dos, String text) {
dos.writeUTF("TEXT");
dos.writeUTF(text);
dos.flush();
}
Why do you want the *Stream to convert to the *Writer.
You can do what you want to do with *Stream.
Socket s = new Socket();
DataOutputStream stream = new DataOutputStream( s.getOutputStream() );
byte[] bytes = "INFO".getBytes();
stream.write(bytes);
//....
bytes = "DATA".getBytes();
stream.write(bytes);