Java client/server issue sending objects over sockets [duplicate] - java

This question already has answers here:
Java socket/serialization, object won't update
(2 answers)
Closed 7 years ago.
I'm creating a standard multi-client/server program in Java. The server accepts connections and spawns a new thread to handle each one. The client also spawns a thread to wait for messages from the server. The client and server communicate by passing Message objects through ObjectInputStream and ObjectOutputStreams.
The initial handshake works fine. When the client starts, it opens a socket connection to the server. The server accepts the socket, sends a Message to the client that the connection was successful. Then the client sends its username back, and both client and server start waiting for messages.
Then I send some text from my client which creates a chat message, and sends it successfully to the server. The server receives this message, and attempts to send it out to all connected clients, which it does (there's only one). The problem is that this message never gets back to the client.
// This is Message.send
public void send(ObjectOutputStream stream) throws IOException{
stream.writeObject(this);
}
// ClientThread.run
public void run(){
try {
out = client.getOutputStream();
out.flush();
ObjectInputStream in = client.getInputStream();
Message msg = null;
int len;
byte[] bytes = null;
int i = 0;
// Continuously read new Messages from the server
while(true){
msg = (Message)in.readObject();
processInput(msg);
}
} catch (Exception e) {
Util.showError(e.getMessage(), "Connection Error");
}
System.out.println("Client exited");
}
// ServerThread.run
public void run() {
try {
out = new ObjectOutputStream(client.getOutputStream());
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
Message msg = null;
while(client.isConnected()){
msg = (Message)in.readObject();
processInput(msg);
}
in.close();
client.close();
} catch (Exception e) {
server.addMessage(e.getMessage());
}
}

I don't see any calls to flush(), without which the data may never make it from point a to point b.
I'd recommend using the ObjectOutputStream atop a ByteArrayOutputStream, and pushing the resulting byte array across the wire, and then reversing the process on the other end.

Related

Java TCP - Client Server help needed

Hi and thanks in advance.
I am currently trying to create a client server program where the server responds to the client based on different requests coming in from the client.
Here is what I am trying to do for the first of the requests (the issue is the same for all of the clients different requests to the server, so fixing just this would help me fix all of them):
1) The client connects to the server
2) The client sends logon information to the server
3) The server checks the logon information for validity
4) The server sends a response saying that login was successful.
5) Client receives and displays response.
Here is the Client (the first try block is located in the client frame, the second within an action listener for a button on the client frame):
try
{
mySocket = new Socket("localhost", 2016);
}
catch (UnknownHostException e1)
{
e1.printStackTrace();
}
catch (IOException e1)
{
e1.printStackTrace();
}
try
{
DOS = new DataOutputStream(mySocket.getOutputStream());
DOS.writeUTF(txtName.getText() + " " + txtPassword.getText());
DOS.flush();
DOS.close();
DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());
JOptionPane.showMessageDialog(null, DISLog.readLine());
}
catch(IOException e1)
{
e1.printStackTrace();
}
Server:
System.out.println("Waiting for client....");
ServerSocket myServerSocket = new ServerSocket(2016);
Socket mySocket = myServerSocket.accept();
myClientHandler = new EZFILEHandler(mySocket);
//Log in check
DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());
StringTokenizer ST = new StringTokenizer(DISLog.readLine());
String Name = ST.nextToken();
String Password = ST.nextToken();
//DISLog.close();
boolean Found = myClientHandler.matchUser(Name,Password);
DataOutputStream DOS = new DataOutputStream(mySocket.getOutputStream());
if (Found == true)
{
DOS.writeUTF("You are logged in.");
DOS.flush();
LoggedIn = true;
}
if (Found == false)
{
DOS.writeUTF("You could not log in.");
DOS.flush();
}
Here is the code for the ClientHandler mentioned in the Server code:
public EZFILEHandler(Socket newConnectionToClient)
{
try
{
mySocket = new Socket("localhost", 2016);
}
catch(Exception e)
{
e.printStackTrace();
}
}
Running the above code will give a Socket is closed exception at this line in the client: DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());, so I then tried commenting out the line: DOS.close(); in the client to keep the socket open, but that causes the button which calls the client code to freeze the program and points to this line if I terminate the program: JOptionPane.showMessageDialog(null, DISLog.readLine());.
So my question is this: How do I allow the client and server to respond to each other in different ways without the socket closing or the jswing freezing from not being allowed to finish processing?
Also, how would it be possible for me to allow multiple clients to logon to the server and all their requests still be processed safely?
Thank you.
If you are writing a Swing program, your socket communication should be on its own SwingWorker thread.
Let's ignore that, and pretend it is just debugging code, not intended to stay.
DISLog.readLine() will read until it reaches the newline character, or the end of the input stream. The server is executing (say) the following:
DOS.writeUTF("You are logged in.");
DOS.flush();
No newline there. And flush() does not close the stream; it simply ensures all the characters are sent, not left in the buffer to be combine with the next set of characters to send.
Catch-22? Yup! The client is waiting for \n, and the server is waiting for more commands from the client.
Change the client to use readUTF().
Update Looks like you need to change the server to use readUTF() as well. The server is probably not getting past the new StringTokenizer(DISLog.readLine()) call unless the client closes the socket.

Reusing sockets in server-client

I am trying to create a client-server system: my server is a raspberry pi which is running a python webserver on it, and my client is on a different pc and is written is Java. The idea is that the server collects data and when it gets a request from a client, it sends the data to the client.
My client should request the data, wait for 10 seconds and request again etc.
Currently this system is working, but after a day or so, the client starts getting a lot (but not continuously) socket timeouts. I think that this may be the case because for each request I create a new socket for communication and I think that after a day the sockets run out or something like that. This is the code the client executes every 10 seconds:
public static String getData() throws Exception {
TreeSet<Integer> primes = MathUtils.primesSieve(10000);
try {
String data = "";
Socket socket = new Socket(SERVER_ADDRESS, SERVER_PORT);
socket.setReuseAddress(true);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int msg = ColUtils.drawRandomlyWithReplacement(primes, 1, ArrayList::new).get(0);
out.write(msg+"");
out.flush();
String input;
while ((input = in.readLine()) != null) {
data += input;
if (!data.endsWith("#" + prod(msg))) {
throw new Exception("WRONG ECHO");
}
}
socket.close();
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
I tried fixing it by having a socket which is a member of the encapsulating class, but after a singe request the inputstream stopped working. Is there any way where I can keep using a single socket for ALL communications with the server? Or is this the recommended way of doing this sort of communication?
Try first closing the socket and input, output streams. As in your code there is no quarantee that you are releasing the acquired objects.
PrintWriter out = null;
BufferedReader in = null;
Socket socket = null;
try {
...//your statements
} catch (Exception ex) {
//catch or whatever
} finally {
if (out != null) out.close();
if (in != null) in.close();
if (socket != null) socket.close();
}
try to make the Socket object static If possible that would created only once and read the data every 10 sec
Otherwise u can instantiate it before calling the getData method and then read it.
Doing so will make only 1 copy of Socket.
And I don't think u are running out of ports.
The reason might be quit simple that your Program is not receiving the data before the time out. and it is a normal case in a bad network
Socket generally waits indefinitely until it receives data if the timeout is not set Programmatically

Start doPost method in java servlet from arduino using ethernetclient

I've got a java tomcat servlet with a doPost method and a webpage running on that server. I set up a very basic test with a html button on my web page, that when pressed calls the doPost method. What i would like to know is how i would do this from the arduino?
I tried
client.println("POST /Project/index.html?acctID=1234567 HTTP/1.0");
as a means to call the doPost method and pass it an "acctID", this however doesn't call that doPost method. I don't have a very good understanding of how to send get/post from ethernetclient in arduino (i imagine it doesn't work quite how i'm thinking it does), so hopefully someone can help me understand, thanks!
In response to comment:
So i've continued to play with this and what i've done at this point is I've made a server on my java side that sends data (via sockets) to an arduino server that i've made. What i'm trying to do now is send a simple, small piece of data back to my java program/servlet. What i've tried so far that is the code posted above on the arduino side, and on the java side i've got a simple server:
private static void listenForArduino() throws IOException, ClassNotFoundException {
//static ServerSocket variable
ServerSocket server;
//socket server port on which it will listen
int port = 9876;
//create the socket server object
server = new ServerSocket(port);
//keep listens indefinitely until receives 'exit' call or program terminates
while(true){
System.out.println("Waiting for client request...");
//creating socket and waiting for client connection
Socket socket = server.accept();
//read from socket to ObjectInputStream object
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
//convert ObjectInputStream object to String
String message = (String) ois.readObject();
System.out.println("Message Received: " + message);
//create ObjectOutputStream object
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
//close resources
ois.close();
oos.close();
socket.close();
//terminate the server if client sends exit request
if(message.equalsIgnoreCase("exit")) break;
}
System.out.println("Shutting down Socket server!!");
//close the ServerSocket object
server.close();
}
I never receive a response, it stalls on this line
server = new ServerSocket(port);
My arduino code (that pertains to this):
if (client.connect(ip, 9876)) {
Serial.println("connected");
client.println("POST /NFCPaymentProject/index.html?acctID=1234567 HTTP/1.0");
client.println();
} else {
Serial.println("connection failed");
}

EOF Exception in a thread using sockets

I have the code below:
while (true)
{
lengthInput = instr.readByte();
// Other code
}
The thing is that I'm using a client to send information to the socket, but after it finishes I got EOF Exception and it brokes the thread, what I need is to manages this and dont stop the thread, because I need to send more information and be able to read it.
Thanks in advance for your help.
I guess the problem is related to your socket initialization. You probably need to check if your client socket indeed successfully create a socket and bind to a specified port. You may also check your client really send data to the outstream and flush to the server side. I have a small project on Android emulators with socket communication. Both my client and serve extends from Java Thread class. Maybe you can gain some idea seeing my code below.
The client side
try {
socket = new Socket(InetAddress.getByAddress(new byte[]{10, 0, 2, 2}),
Integer.parseInt(remote_port));//note we must keep the addr#10.0.2.2
// write out
out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(out_msg);
out.flush();
// read in
in = new ObjectInputStream(socket.getInputStream());
socket.setSoTimeout(1000);
in_msg.set_message((Message)in.readObject());
// close all
out.close();
in.close();
socket.close();
return true;
}catch(InterruptedIOException E){}
The server side
while (true) {
try {
// read in message
Socket ClientSocket = serverSocket.accept();
Message out_msg = new Message();
// read in message
ObjectInputStream in = new ObjectInputStream(ClientSocket.getInputStream());
Message in_msg = (Message) in.readObject();
//Log.d(TAG, "recv" + " content:" + in_msg.msg2Str());
message_process(in_msg, out_msg);
// write out message
ObjectOutputStream out = new ObjectOutputStream(ClientSocket.getOutputStream());
out.writeObject(out_msg);
out.flush();
} catch(Exception E){}
}

Java - Socket - Freeze

i've a minimal server which wait until a client connect ,then he start a thread which will send a reply back to the client, the problem is the reply.
This is the code of the server:
int port = 1234;
ServerSocket servSock = null;
servSock = new ServerSocket(port);
while (true) {
Socket link = servSock.accept();
serverThread st = new serverThread(link);
st.start();
}
This is the code of the run() method of the thread,the one which send the answer back, sk is the socket "link" passed by parameter in the server code
public void run() {
String dato = "";
InputStream i = null;
try {
i = sk.getInputStream();
} catch (IOException ex) {
Logger.getLogger(serverThread.class.getName()).log(Level.SEVERE, null, ex);
}
Scanner input = new Scanner(i);
//i receive the data sent
while (input.hasNext()) {
dato += input.nextLine();
}
// then i send a reply
DataOutputStream outputStream=new DataOutputStream(sk.getOutputStream());
outputStream.writeInt(1);
outputStream.close();
Client side ( only the code which should receive the answer from the server) :
Socket link;
int valid = 0;
String url="localhost";
int port=1234;
link = new Socket(InetAddress.getByName(url), port);
//i've to send some data to the server
PrintWriter output = new PrintWriter(link.getOutputStream(), true);
String a = new String(Base64.encode(mex));
output.println(createXml(tag, a));
output.flush();
//then i need to receive an answer from the server
DataInputStream answerI = new DataInputStream(link.getInputStream());
while(answerI.available()!=0)// but answerI.available() is always equal 0
valid = answerI.readInt();
answerI.close();
output.close ();
link.close();
With this code the istruction valid = answerI.readInt(); is not reached.
Without the while cycle, the client freeze at line : valid = answerI.readInt();
Can anyone help me?
Thank you in advance
I'm guessing that the server is blocked in a call to input.hasNext(). This will return false when the socket is closed, and its InputStream returns -1 to signal the end of the stream. However, the socket is still open. The client can send another line; the Scanner is blocking to see what the client's next move will be.
There are ways to shutdown "half" of a socket, so that the server can tell that the client has closed its sending channel but can still receive a response.
However, this approach is complicated. I suggest a change to the protocol so that the server can determine when it is allowed to respond.
In this protocol you don't need the reply if it is always '1'. Just close the socket. The client should block in a read() which will return -1 when the server closes the socket.

Categories

Resources