I am developing a GUI program to use in a client/server system that will save data in a Vector. I have an ObjectOutputStream and ObjectInputStream that is created when I make the connection, however I am not sure how to pass it into the new class when i try to open one up. In my Startup class I have a Serializable object (Message m) that is created and passed into different classes to have different fields modified, as well as the connection gets established between the client and server
In my Startup class I have this code...
m.yourName = tmyName.getText();
m.department = tdepartment.getText();
if (m.yourName != null && m.department != null) {
client = new Socket(server, port);
oout = new ObjectOutputStream(client.getOutputStream());
oin = new ObjectInputStream(client.getInputStream());
toutput.setText("Connected");
oout.writeObject(m);
new WhatToDo (m, oout, oin);
}
In the WhatToDo class i have this code...
Message m;
ObjectOutputStream oout;
ObjectInputStream oin;
public WhatToDo(Message a, ObjectOutputStream oout2, ObjectInputStream oin2){
m = new Message();
m = a;
// this is what i'm unsure about and need help with
oout = oout2; //but need to construct oout first
oin = oin2; //but need to construct oin first
}
If i do the new ObjectOutputStream and ObjectInputStream like I did in Startup, i will create a new connection to the server. I wish to use the existing Streams created in Startup in WhatToDo. Thank you for your help in advance!
I'm using an ActionListener with button presses, so the streams will need to be saved in the constructor for later use in the ActionListener.
I wish to use the existing Streams
That is exactly what your code does now. Your comments about 'but need to construct' are incorrect.
Related
I am making a simple application in Java (Animal shelter), it allows you to add animals to the list, edit free places, send email when the free space ends and all the changes are saved when the program closes and loaded after it is turned on.
However, the list of animals (ArrayList) is saved in one file, a list of free places in the second, email address (string) in the third, etc. ...
I have tried to place objects that need to be saved in one collection (ArrayList ), but this file does not load correctly.
Any ideas how to save and read different types in a txt file?
Example of my import/export class:
void autoSave() {
try {
FileOutputStream fout = new FileOutputStream(path);
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(AddAnimalScene.listOfAnimals);
oos.close();
FileOutputStream fout1 = new FileOutputStream(path1);
ObjectOutputStream oos1 = new ObjectOutputStream(fout1);
oos1.writeObject(EditFreeSpaceScene.places);
oos1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
void autoLoad() {
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(path));
ArrayList<Animal> LoadedAnimalList = (ArrayList<Animal>) in.readObject();
in.close();
AddAnimalScene.listOfAnimals = LoadedAnimalList;
ObjectInputStream in1 = new ObjectInputStream(new FileInputStream(path1));
Integer LoadedPlaces = (Integer) in1.readObject();
in1.close();
EditFreeSpaceScene.places = LoadedPlaces;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
A tip: Always read the Javadoc, especially as a beginner. Might be challenging at first, but it will pay off later. In my opinion, consulting the official documentation is always the right way to clear any issues.
From the ObjectOutputStream Javadoc:
Only objects that support the java.io.Serializable interface can be written to streams.
Your Animal class should implement Serializable interface.
On the other hand, if you want to explicitly specify a field should not be serialized, you could use the transient modifier.
First of all, this is a homework problem. That being said, I'm stuck. Googling for java Properties over Sockets results in a lot of irrelevant things.
I'm trying to transfer a Properties object over a socket. The API says it can be done with a Stream or a Writer/Reader, but I can't get it to work. I can do it manually, that is, if I read the file line by line and pass it through a PrintWriter.
On the client side I've got roughly:
socket = new Socket(host, port);
outStream = socket.getOutputStream();
out = new PrintWriter(outStream, true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
reader = new BufferedReader(new FileReader(file));
...
props.load(reader);
props.store(out, null);
On the server side the receiving bits look like:
out = new PrintWriter(sock.getOutputStream(), true);
inStream = sock.getInputStream();
in = new BufferedReader( new InputStreamReader(inStream));
...
props.load(in); // hangs
// doesn't get to code here...
In this case it hangs at the props.load(in). Instead of doing props.load(in), I read it in line by line to make sure props.store(out, null) was working, and the data looks like its being transferred.
Is there something about load/store I don't understand, or is it an issue with the Stream/Writer/Reader?
I think this will answer this question as well as How do I recognize EOF in Java Sockets? and What can I send to an InputStream to signify EOF has been reached?
I had a similar problem; my dilemma was that I had a client/server request-response protocol where one of the requests included a stream sent from the client side using clientProps.store(). The corresponding serverProps.load() on the server side never returns because it needs to see the "end-of-file" - which in Java means the client has to close it's stream; resulting in the socket connection closing. The unwanted result was that, not only could I not keep the socket open for indefinite request-response exchanges, I couldn't even keep it open for the server to send its reply.
I hated Java for making me do that, even more because the documentation for Properties.load() says:
The specified stream remains open after this method returns.
That could never happen if it's detecting end-of-file by seeing the stream close!! Anyway, now, I still love Java because it allowed me to use this solution (might not be useful if you have any special encoding or localization of the data you are streaming):
I used this on the client side:
PrintWriter toServer;
Properties clientProps = new Properties();
// ... code to populate the properties and to
// construct toServer from the socket ...
clientProps.store(toServer, null);
toServer.write('\u001A'); // this is an old-school ASCII end-of-file
toServer.flush();
On the server side I extended Reader to detect the 1A and return -1 (so that the serverProps.load() learns about the end-of-file in the normal way (by seeing -1 returned from a call to read()), but below that, the stream and the socket stay open.
BufferedReader fromClient;
Properties serverProps = new Properties();
// ... code to construct fromClient from the socket ...
serverProps.load (new PropReader (fromClient));
/////
private static class PropReader extends Reader {
BufferedReader src;
boolean eof=false;
private PropReader(BufferedReader fromClient) {
super();
src=fromClient;
}
#Override
public int read(char[] cbuf, int off, int len) throws IOException {
int inCount;
if (!eof) {
inCount = src.read(cbuf, off, len);
if (inCount > 0) {
// we read a buffer... look at the end for the EOF that the client used to mark the end of file
if (cbuf[off+inCount-1] == '\u001A') {
--inCount; // don't send eof with the data
eof = true; // next time... we'll return -1
}
}
} else {
inCount = -1;
}
return inCount;
}
#Override
public void close() throws IOException {
src.close();
}
I'm coding a little program that checks an online store for new items in a specific department. When it does find that a new item has been added, it's supposed to send that info to a simple IRC-bot, which in turn writes it out in a channel so I can see it immediately.
The problem is that the IRC part only works once. So while the parser successfully announce every new item at the store in my console, the IRC bot only shows the first. So the problem is most likely my socket code.
I shall tell you that I'm a complete noob with sockets, so it can be a really simple problem(for you, that is).
Enough talk, here's the relevant code:
The bot:
public void openSocket() throws IOException{
serversock = new ServerSocket(1551);
Socket sock = serversock.accept();
BufferedReader incoming = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String inString = incoming.readLine();
sendMessage("#channel", inString);
}
public static void main(String[] args) throws Exception {
XanaduBot bot = new XanaduBot();
bot.setVerbose(true);
bot.connect("irc.server.net");
bot.joinChannel("#channel");
bot.openSocket();
}
And the socket part on the scraper:
if(old == false){
Socket client = new Socket("localhost",1551);
DataOutputStream toBot = new DataOutputStream(client.getOutputStream());
String infoToSend = "New product! "+ info;
toBot.writeBytes(infoToSend + '\n');
toBot.flush();
System.out.println(infoToSend);
}
The variable old is false whenever the program finds a new item. And I know that exceptions are handled pretty bad here, sorry for that!
Any help appreciated!
I ran into a problem while using input/output streams in Java. My thought was to have a DataInputStream to handle receiving text and a PrintStream to pass messages to the server from the server and object(output/input)streams to handle passing piece movements and current board image.
My problem is that the code hangs while it is trying to create the ObjectInputStream in the code below. Is this because I am trying to have multiple input and output streams? If so is there any possible fix I could use?
Socket sock = new Socket("127.0.0.1", 1716);
input = new DataInputStream(sock.getInputStream());
printer = new PrintStream(sock.getOutputStream());
System.out.println("Test 1");
zelda = new ObjectInputStream(sock.getInputStream());
System.out.println("Test 2");
link = new ObjectOutputStream(sock.getOutputStream());
System.out.println("Test 3");
I have a lot of Legend of Zelda references in my server source code and the code is rather large. The previous source code is for the client and although the server connects here is where I call ObjectOutputStream.
ObjectOutputStream ganandorf;
for(int i = 0; i < clients.size(); i++)
{
try
{
ganandorf = new ObjectOutputStream(clients.get(i).getOutputStream());
ganandorf.write(1);
ganandorf.flush();
ganandorf.writeObject(something);
ganandorf.flush();
}
Don't try to use two different kinds of streams/readers/writers on the same underlying connection. You will encounter buffering issues at both ends that make it basically impossible.
I would use ObjectInputStream and ObjectOutputStream and just write objects.
The constructor of ObjectInputStream blocks until it receives the header that is written by the constructor of ObjectOutputStream, so if you are constructing both you must construct the ObjectOutputStream first. You don't need to write anything and you don't need to flush it either, it does that itself.
I think you can only ask for 1 inputStream reference:
InputStream baseInputStream = sock.getInputStream();
input = new DataInputStream(baseInputStream);
zelda = new ObjectInputStream(baseInputStream);
same goes for outputStreams
I never found out what happened with ObjectInputStream, but I switched to DataInputStream and I'm currently modifying my code so it sends the piece name, x location, and y location in one string that will get broken up at the client and the board will be modified accordingly
Open a socket on a different port and use that to create new streams.
I am feeling really stupid right now guys.... basically I am connecting over TCP on a local machine... and when I try to make the In/out streams at the client it wont get passed creating the object input stream. What gives? This stops after printing 2... no exceptions or anything... This isn't the first time I've used this class which is partialy why I am puzzled.
try {
System.out.println("1");
mySocket = new Socket("localhost", 11311);
System.out.println("12");
oos = new ObjectOutputStream(mySocket.getOutputStream());
System.out.println("2");
ois = new ObjectInputStream(mySocket.getInputStream());
System.out.println("13");
} catch (Exception e) {
e.printStackTrace();
}
From the specification of ObjectInputStream:
This constructor will block until the corresponding ObjectOutputStream
has written and flushed the header.
(For future readers:) I had the same problem because i made a silly change in server program and didn't test it for a long time then i was confused about why program is locked.
ServerSocket accepts the connection (responderSocket = serverSock.accept();) then suddenly for a inapropriate if (The silly change i mentioned!) program jumps out of the thread and because i didn't add a finally block to close streams and sockets the socket was left abandoned w/o sending or recieving anything (even stream headers). So in client side program there was no stream header (When i debbugged The code i saw that the last function executed before lock was:
public ObjectInputStream(InputStream in) throws IOException {
verifySubclass();
bin = new BlockDataInputStream(in);
handles = new HandleTable(10);
vlist = new ValidationList();
enableOverride = false;
readStreamHeader(); //// <== This function
bin.setBlockDataMode(true);
}
readStreamHeader();)
So be careful about what happens in server side, maybe problem isn't where you expecting it!