Hello Im writing an app in which client sends name of room to server, server creates it and then sends back whole list of rooms. I have problem with receiving this object from server also whats interesting when I close clients' app and open again I have list of rooms just like it should be. I refresh room list in client app but its always empty only reopening helps that's pretty weird and I don't know an issue of this.
On client side:
getIs() method is returning is object
getOs() method returning os object
this.os = new ObjectOutputStream(clientSocket.getOutputStream());
this.is = new ObjectInputStream(clientSocket.getInputStream());
private void createRoom(ActionEvent event) {
String roomName = "CreateRoom ";
roomName += setRoomName();
String response = null;
try {
client.getOs().writeObject(roomName);
response = (String) client.getIs().readObject();
System.out.println(response);
} catch (IOException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void refreshRooms() {
String response = null;
try {
client.getOs().writeObject("RefreshRooms");
response = (String) client.getIs().readObject();
System.out.println(response);
rooms = (Rooms) client.getIs().readObject();
System.out.println("Print in client: ");
rooms.printAllRooms();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Server:
this.os = new ObjectOutputStream(connection.getOutputStream());
this.is = new ObjectInputStream(connection.getInputStream());
public void run() {
String inputRequest = null;
try {
while((inputRequest = (String) ois.readObject()) != null) {
System.out.println(inputRequest);
handleRequest(inputRequest);
}
} catch (IOException | ClassNotFoundException e) {
System.out.println("Client has disconnected.");
e.printStackTrace();
}
}
private void handleRequest(String request) {
String response = null;
String[] msg = request.split(" ");
if(msg[0].equals("CreateRoom")) {
try {
oos.writeObject("You want create a room.");
Room newRoom = new Room(msg[1]);
rooms.addRoom(newRoom);
System.out.println("Created room: " + newRoom.getName());
System.out.println("\n Print after creation: ");
rooms.printAllRooms();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if (msg[0].equals("RefreshRooms")) {
try {
oos.writeObject("You want list of rooms.");
System.out.println("Print before send.");
rooms.printAllRooms();
oos.writeObject(rooms);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
///EDIT:
So I removed PrintWriter and BufferedReader objects and now Im using only Object Streams. What doesn't work now is:
I create some rooms one after another and then refresh rooms list on clients app - in that case I get all rooms
But when I create one room refresh then create another and refresh I get only 1 room after 2nd refresh, so basically when I refresh server sends me always the same object from 1st send and I don't know how to change it.
Also Im printing these rooms on server side and always get all rooms so room creation is OK.
You could try to flush the buffered streams:
os.flush()
This will force the stream to actually send the bytes of the serialized object. Without that, the BufferedOutputStream might just wait around and buffer data, as the name says. This is done so that the size of the sent packets does not become too small, which would result in a lot of overhead if you want to send multiple objects.
If you are done, you should close the stream anyway.
Related
I'm setting up a basic client server program. Right now the client is simply sending an object with a command string in it to the server and the server is acknowledging it. This is done using a JFrame with buttons on it. It seems to work ok, except the client seems to be sending multiple requests instead of just one.
Inner class within my Client code:
private class CommandHandler implements ActionListener{
FTPCommand c;
ObjectOutputStream oos;
#Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd == "DIR"){
c = new FTPCommand("DIR");
}
if (cmd == "CHDIR"){
String newDirectory = JOptionPane.showInputDialog("Please enter directory to change to:");
c = new FTPCommand("CHDIR", newDirectory);
}
try {
oos = new ObjectOutputStream(sock.getOutputStream());
oos.writeObject(c);
oos.flush();
//System.out.println("Command: " + c.getCommand() + ", sent successfully");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
Server:
public void run(){
ObjectInputStream in;
try {
in = new ObjectInputStream(sock.getInputStream());
FTPCommand cmd = (FTPCommand) in.readObject();
System.out.println("Received command: " + cmd.getCommand() + " at " + System.currentTimeMillis());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
So if I click on the DIR button just once, this is the output I get, although sometimes it might just be one or two lines:
Received command: DIR at 1390572358017
Received command: DIR at 1390572365578
Received command: DIR at 1390572377229
Why is it sending multiple requests?
Check inside the constructor of FTPCommand; that how many time... it has been called... If thrice .... trace the calling methods.
It turns out that this was the result of the client holding onto previous connections, and sending requests through all open sockets.
I'm currently using the library JSON-io. I created a desktop application which when a person want to log in in the system send an JSONObject with his username and password. Then the server send back the response if the person is allowed or not (also a JSONObject). Until here everything works fine.
Now i want to make an Android app. I take the same code than before for login but the application crashes.
The code for login is launch from an AsyncTask and i put the permission to access to Internet to the Manifest.
I perform some testing and it occurs that the method write of JSONWriter "delete" my JSON because on the server side he receives this : {}. I tried to hardcode the JSONObject on the server side (the server's code works fine because we can use the desktop app) but this time the readObject on the android App receives also {}.
We tried to send jsonObject.toString() and this time it worked (except that the server isn't configured to handle a string).
Do anyone knows why on android the two methods write and readObject are deleting the JSON ?
Thank you.
EDIT:
Here the code i wrote:
On the android App
protected Boolean doInBackground(Void... params) {
// 3 : create a JSON object and send it to server for verification
JSONObject loginJS = new JSONObject();
try {
loginJS.put("type", Type.LOGIN); // Type is an enum
loginJS.put("username", userName);
loginJS.put("hash", mPassword);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
User user = new User();
System.out
.println("User created and ready to connect to the spu for login");
user.connexionToSPU(); // This method works
System.out.println("LoginJS = "+loginJS.toString()); At this point the print of the JSON is fine we have {"type":"Login", ....}
user.sendToSPU(loginJS); //This is where there's a problem
// 4 : wait response
JSONObject loginResponseJS = user.receiveFromSPU(); // And when i hard code the JSON on the server side receiveFromSPU get a empty JSON
Method connexionToSPU:
public void connexionToSPU() {
jswSPU = null;
jsrSPU = null;
Socket socket = null;
try {
socket = new Socket(prop.readPropertiesXML("IP_adress_server"),
Integer.parseInt(prop.readPropertiesXML("port_server")));
} catch (NumberFormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
jswSPU = new JsonWriter(socket.getOutputStream());
jsrSPU = new JsonReader(new BufferedInputStream(socket.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
sendToSPU method
public void sendToSPU(JSONObject json) {
try {
jswSPU.write(json);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ReceiveFromSPU method
public JSONObject receiveFromSPU() {
JSONObject json = null;
try {
json = (JSONObject) jsrSPU.readObject();
System.out.println("JSON FROM THE SERVER : "+json.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return json;
}
Hope it will be sufficiently clear.
Thank you
I am working on a small project where I have to communicate to an Android app on my phone and with Arduino.
Now, I have the connection between Android and laptop (used as server, I have a small amount of data stored here), and I can change the contents of text files when I send certain instructions from Android app.
This is how I do it:
I have a ServerSide class that listens on port 3000 and I read the text I stream from phone, then I make certain changes in text files for different messages.
The code:
public class ServerSide {
public static void main(String[] args) throws IOException {
while (true) {
ServerSocket serverSocket = null;
// check if client is trying to connect
try {
serverSocket = new ServerSocket(3000);
} catch (IOException e) {
System.err.println("Cannot communicate on this port");
System.exit(1);
}
Socket clientSocket = null;
// move to another socket
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed");
System.exit(1);
}
// stream that will be sent to client. "true" is for creating from
// existing
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
true);
// stream that comes from the client
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
String recivedData, sendData;
ServerProtocol communicationProtocol = new ServerProtocol();
while ((recivedData = in.readLine()) != null) {
sendData = communicationProtocol.process(recivedData);
out.println(sendData);
System.out.println("The text should now be written in file");
System.out.println(sendData);
}
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
}
}
ServerProtocol.process() is the method that updates the files
By the way, this is a good version of a program that implies connection via sockets (if anyone should need information about this, at a future time).
Everything works great, I can see my updates immediatly after I send them, the server is up and running, waiting for messages.
I forgot to mention, I am new to java and a novice in programming, in general.
Now, I want this code I managed to write to be part of a bigger "server". By "server", I understand a program that "serves", performs a service. When it runs on my laptop, it takes information that comes from the Internet on the port I specify, change things in files according to my messages, keeps theese files updated and in the same time it uses theese files to "interpert" data I send from phone, and then sends according messages to Arduino Shield. (THIS IS WHAT I WANT TO ACHIVE)
I guess that what I miss, is the following:
How do i make this code I have written untill now, part of a bigger project, that does all that?
I managed to split the project in 3 parts:
Communication laptop - Android
Constant data updates
Communication laptop - Arduino
I've done some research, and I came across threads. So I thought about having the communication with Android on a separate thread of a MainServer. I clearly got it wrong, because it doesn't do what I expect it to do, so here is the code:
I create the ServerSide class that extends Thread, and has a run() method that should be called when I start the thread. It behaves just like the one above, but the executing code lays inside a run() method:
public class ServerSide extends Thread {
#Override
public void run() {
while (true) {
ServerSocket serverSocket = null;
// check if client is trying to connect
try {
serverSocket = new ServerSocket(3000);
} catch (IOException e) {
System.err.println("Cannot communicate on this port");
System.exit(1);
}
Socket clientSocket = null;
// move to another socket
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed");
System.exit(1);
}
// stream that will be sent to client. "true" is for creating from
// existing
PrintWriter out = null;
try {
out = new PrintWriter(clientSocket.getOutputStream(), true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// stream that comes from the client
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String recivedData, sendData;
recivedData = null;
sendData = null;
ServerProtocol communicationProtocol = new ServerProtocol();
try {
while ((recivedData = in.readLine()) != null) {
try {
sendData = communicationProtocol.process(recivedData);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.println(sendData);
System.out
.println("The text should now be written in file");
System.out.println(sendData);
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.close();
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Then, I have the MainServer:
public class MainServer {
public static void main(String[] args) throws IOException {
System.out.println("Started");
Thread myThread = new Thread(new ServerSide());
myThread.start();
System.out.println("Started2");
while (true);
}
}
It should do nothing, just start the new thread. I expect this new thread do act just like the old ServerSide above (the one with main() method).
Someone, please tell me where I got it wrong !?!
Well, two things seem a little unusual about the MainServer class. First, creating a thread with new Thread(new ServerSide()) will cause a compilation error. There are two ways to fix this: either you make ServerSide implement the Runnable interface instead of extending Thread, or you create the thread with new ServerSide(). Second, the infinite loop at the end of main is useless and can be removed. The main method runs in its own thread, and if it finishes, all other threads keep running, and there is no need to keep main alive. The program will indeed keep running when main finishes, which may seem strange, but that's what will happen.
Everything was OK here, my problem was actually my phone connection to wi-fi, I was a bit too far in the back yard :)
I've been trying to debug this for 2 hours and i just can't explain it.
I have a server and a client. (server manages some Auctions).
What happens:
The client request something , server sends data back and client receives it just fine.
The client sends something to the server, and the server updates some data.
The client makes the same request as first time (1.), the server send back the updated
data, but the client does not receive the new update data, instead it receives the old data (as it got it in the first request (1.).
The data that is being sent is just a Java Bean with two List-s.
And the code:
// CLIENT CLASS
// creates socket, sends and listens on the socket
// listening is done on a separate thread
public class ServerConnector {
private Socket socket = null;
private ObjectOutputStream out = null;
private Display display;
private ServerListener listener;
public ServerConnector(Display display) {
this.display = display;
try {
socket = new Socket("localhost",33333);
out = new ObjectOutputStream(socket.getOutputStream());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
listener = new ServerListener(socket, display);
new Thread(listener).start();
}
public void sendRequest(Request request) {
try {
out.writeObject(request);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class ServerListener implements Runnable {
private Socket socket;
private ObjectInputStream in = null;
private Display display;
public ServerListener(Socket socket,Display display) {
this.socket = socket;
this.display = display;
try {
in = new ObjectInputStream(socket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
Response response =null;
try {
while ((response = (Response)in.readObject()) != null) {
if (response.getCars().size() > 0) {
display.showAvailableCars(response.getCars());
}
if(response.getAucs().size() > 0) {
List<Auction> auctionz = response.getAucs();//HERE 1st time it gets the GOOD data, 2nd time should get UPDATED DATA but instead receives the OLD DATA (same as 1st time).
display.showOpenAuctions(auctionz);
}
response = null;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//CLIENT CLASS
// controls when something should be sent, and print out responses
public class Display {
Scanner console = new Scanner(System.in);
ServerConnector server = new ServerConnector(this);
List<Car> cars;
List<Auction> aucs;
public void show() {
int opt = 0;
System.out.println("1. Show available cars for auction.");
System.out.println("2. Show open auctions.");
opt = console.nextInt();
Request request = new Request();
if (opt == 1)
request.setRequest(Request.GET_CARS);
if (opt == 2) {
request.setRequest(Request.GET_OPEN_AUCTIONS);
}
server.sendRequest(request);
}
public void showAvailableCars(List<Car> cars) {
int i = 0;
for (Car c : cars ){
i++;
System.out.println(i +". " + c.getMaker() + " " + c.getModel() + " price: " + c.getPrice());
}
System.out.println("Select car to open Auction for:");
int selectedCar = console.nextInt();
if (selectedCar != 0) {
if (selectedCar <= cars.size()) {
Request request= new Request();
request.setRequest(Request.OPEN_AUCTION);
Car c = cars.get(selectedCar-1);
request.setCar(c);
server.sendRequest(request);
}
}
show();
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
public void showOpenAuctions(List<Auction> aucs2) {
int i = 0;
for (Auction auc : aucs2) {
i++;
System.out.println(i+ ". " + auc.getCar().getModel() + " " + auc.getCar().getMaker() + " last price: " + auc.getPrice());
}
System.out.println("You can now make offers");
System.out.println("Input auction number:");
int selectedAuction = 0;
selectedAuction = console.nextInt();
if (selectedAuction > 0 && selectedAuction <= aucs2.size()) {
System.out.println("Offer new price:");
int price = console.nextInt();
Request request= new Request();
request.setRequest(Request.MAKE_OFFER);
request.setAuctionId(aucs2.get(selectedAuction-1).getId());
request.setPrice(price);
server.sendRequest(request);
}
show();
}
public void setOpenAuctions(List<Auction> aucs2) {
this.aucs = aucs2;
}
}
// SERVER CLASS : send and receives
public class ClientManager implements Runnable {
private AuctionManager manager = new AuctionManagerImpl();
private Socket client;
private ObjectInputStream in = null;
private ObjectOutputStream out = null;
public ClientManager(Socket socket) {
this.client = socket;
try {
in = new ObjectInputStream(client.getInputStream());
out = new ObjectOutputStream(client.getOutputStream());
} catch(Exception e1) {
try {
e1.printStackTrace();
client.close();
}catch(Exception e) {
System.out.println(e.getMessage());
}
return;
}
}
#Override
public void run() {
Request req = null;
try {
while ((req = (Request)in.readObject()) != null) {
if (req.getRequest() != null) {
if (req.getRequest().equals(Request.GET_CARS)) {
Response response = new Response();
response.setCars(manager.getAvailableCars());
out.writeObject(response);
continue;
}
if (req.getRequest().equals(Request.OPEN_AUCTION)) {
manager.openAuction(req.getCar());
continue;
}
if (req.getRequest().equals(Request.GET_OPEN_AUCTIONS)) {
Response response = new Response();
response.setAucs(manager.getHoldedAuctions()); //this line ALWAYS sends to the client GOOD, UPDATED DATA
out.writeObject(response);
out.flush();
continue;
}
if (req.getRequest().equals(Request.MAKE_OFFER)) {
Auction auction = manager.getOpenAuction(req.getAuctionId());
manager.updateAuction(auction, req.getPrice(),client.getRemoteSocketAddress().toString());
continue;
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
It could be because you are using ObjectOutputStreams. Remember that ObjectOutputStreams will cache all objects written to them so that if the same object is written again in the future it can write a back-reference instead of re-writing the whole object. This is necessary when writing an Object graph.
Your code fragment:
if (req.getRequest().equals(Request.GET_CARS)) {
Response response = new Response();
response.setCars(manager.getAvailableCars());
out.writeObject(response);
continue;
}
is writing the object returned by manager.getAvailableCars(). The next time a request is received the same object (but now with different contents) is written - but the ObjectOutputStream doesn't know about the new contents so it just writes a back-reference. The ObjectInputStream at the other end sees the back-reference and returns the same object it read last time, i.e. the original data.
You can fix this by calling ObjectOutputStream.reset() after each response. This will clear the stream's cache.
See ObjectOutputStream.writeUnshared() and .reset().
Ok. I just found out the solution.
from here http://java.sun.com/developer/technicalArticles/ALT/sockets/ :
Object Serialization Pitfall
When working with object serialization it is important to keep in mind that the ObjectOutputStream maintains a hashtable mapping the objects written into the stream to a handle. When an object is written to the stream for the first time, its contents will be copied to the stream. Subsequent writes, however, result in a handle to the object being written to the stream. This may lead to a couple of problems:
If an object is written to the stream then modified and written a second time, the modifications will not be noticed when the stream is deserialized. Again, the reason is that subsequent writes results in the handle being written but the modified object is not copied into the stream. To solve this problem, call the ObjectOutputStream.reset method that discards the memory of having sent an object so subsequent writes copy the object into the stream.
An OutOfMemoryError may be thrown after writing a large number of objects into the ObjectOutputStream. The reason for this is that the hashtable maintains references to objects that might otherwise be unreachable by an application. This problem can be solved simply by calling the ObjectOutputStream.reset method to reset the object/handle table to its initial state. After this call, all previously written objects will be eligible for garbage collection.
The reset method resets the stream state to be the same as if it had just been constructed. This method may not be called while objects are being serialized. Inappropriate invocations of this method result in an IOException.
I am trying to create a UDP listener that will listen on a separate thread. It works fine the first time but when I stop the connection and then start it again it gives me errors.
listenerRunnable = new Runnable() {
public void run() {
//This thread will listen keep listening to the UDP traffic and put it to the log source string
try {
sock = new DatagramSocket(portNumber);
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(keepListening) {
try {
pack = new DatagramPacket(recievedData, BUFFERSIZE);
sock.receive(pack);
String data = new String(pack.getData(), 0, pack.getLength());
addToLog(data);
System.out.println(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sock.close();
}
}
};
/**
* Function to start the listening thread.
*/
public void startListening(int portNum) {
keepListening = true;
portNumber = portNum;
listenerThread = new Thread(listenerRunnable);
logSource_buffer = "";
logSourcehtml_buffer = "";
logSourcehtml_temp = "";
ipListIndex_beg = 0;
ipListIndex_end = -1;
if(!listenerThread.isAlive()) {
listenerThread.start();
}
}
/**
* stops the listening thead. When the listening thread sees that keepListening is set to false
* it will reach the end of its loop, close the socket, and the thread will die.
*/
public void stopListening() {
keepListening = false;
}
It gives me the following error:
logUpdatingThread has entered synchronized block!!!
java.net.SocketException: Unrecognized Windows Sockets error: 0: Cannot bind
at java.net.PlainDatagramSocketImpl.bind0(Native Method)
at java.net.PlainDatagramSocketImpl.bind(Unknown Source)
which points to the line with sock.recieve(pack);
It seems like for some reason the socket isn't closing because, I think, its waiting at sock.recieve(pack) and never gets out of the while loop to close the socket. How would I get around this though?
Thanks
As Peter Tillemans said, you should set a receive timeout so that you're not sitting there trying to receive() for ever.
Also, keep hold of the Thread object returned by new Thread(listenerRunnable) so that your stopListening() method can wait for the thread to die:
public void stopListening() {
keepListening = false;
listenerThread.join();
}
You'll have to add a setSoTimeout(timeout) before calling receive. This will regularly throw SocketTimeoutExceptions, but keeping the Datagram socket open. This will allow you to regularly check the loop variable.
Additionally you should move the loop inside the first try-catch block and add a finally block to close the socket.
like :
try {
sock = new DatagramSocket(portNumber);
sock.setSoTimeout(250);
while(keepListening) {
try {
pack = new DatagramPacket(recievedData, BUFFERSIZE);
sock.receive(pack);
String data = new String(pack.getData(), 0, pack.getLength());
addToLog(data);
System.out.println(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
sock.close();
}