Win a copy of Classic Computer Science Problems in Swift this week in the iOS forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Client/Server programming  RSS feed

 
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello everyone. Once again I am relying on your expertise and good will to help out a nooby beginner.
I am sure I made a mess and my lack of knowledge transpires from every line of code but I am still learning

Anyway the thing I am doing is very simple. I have to make a server, a client and gui for the client(strictly AWT).
The client is supposed to take input from the user and send it to the server which will sum the 2 nubers and send them back.
But I am making a mess with the listeners so any help here is appreciated. Here is my code.

Server and "calculator" logic



Here is the client with gui.



Its not working. I haven't yet included the result in the ui window, but it does not print in the console either.
What am I doing wrong? Even unralated feedback is appreciated, about any part of the code.
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I forgot I deleted the lines for sending the data to the server. Just pretend they are there in the textfield listeners which is where I had them.
 
Rancher
Posts: 2946
32
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How are you trying to debug the code to see what it is doing?
I use print statements, lots of print statements that print messages to show where the code is executing and what values variables have.
 
Sheriff
Posts: 23491
46
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have to say, I'm very confused about those listeners.

As I understand it, you have a button which says "Submit" to the user. But clicking on it doesn't submit the question to the server, as I would expect. You also use a MouseListener to listen for clicks on the button, whereas the normal thing to do is to add an ActionListener to the button. I'll assume for now that your method is actually seeing clicks on the button, but you should check that it does.

Then when the Submit button is clicked, you don't send anything to the server. Instead you add some listeners to the TextFields. Yes, I know you said you actually have code to send data to the server, but you said it's in the listeners. So it isn't actually run until the user types something into one of the TextFields. I'm also confused because I don't see where the output of the calculation is supposed to go. And also, this happens every time the Submit button is clicked, so after a while the TextFields could have a large number of listeners attached which all do the same thing.

So the way your GUI works (assuming a lot about the code you accidentally left out) is this: the user clicks on the Submit button. Nothing happens at this point. Then they start typing in the text fields, and every time they type something in one of them, data is sent to the server and the result is, I don't know where it goes. Was it supposed to work that way?
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Clapham wrote:Was it supposed to work that way?


Absolutely not :D
Yes I think I understand this mess a little better now.
I will re-write it.
 
Saloon Keeper
Posts: 4101
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Note that you are calling read/write to pass an int where both of these can only deal with an int that fits in a byte. According to the documentation for writee(): "Writes the specified byte to this output stream. The general contract for write is that one byte is written to the output stream. The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored." So, if your operands 1 & two, and the result fit into the range of -128 through +127 then it should work. Anything else and all bets are off. Also when you do a read() you'll get an int. If the int is -1 then your socket has closed. If it is not -1 then you have to isolate the lower 8 bits with bit manipulation.

I think you should have gotten the socket stuff worked out before even thinking about adding the GUI.
 
Paul Clapham
Sheriff
Posts: 23491
46
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Amadeus Pan wrote:I will re-write it.



If I could suggest: You only need to listen to the button, and when it's clicked send the contents of the text fields to the server. Another text field to contain the server's response would probably help.
 
Carey Brown
Saloon Keeper
Posts: 4101
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't see that you are writing operand1 or operand2 out to the socket anywhere.
 
Carey Brown
Saloon Keeper
Posts: 4101
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A socket is a very low level communication interface. If you want to write an int you'll first need to convert the int into a byte array of length 4 and then write the byte array. Conversely you need to read 4 bytes and reconstruct that back into an int.

It has been suggested that you can send Strings back and forth. Yes you can but you'll have to convert the String into a byte array first, send the length of the array, and then send the array itself. On the read side you'll have to read the length which tells you how many more bytes to read, read those bytes into a byte array, and the convert the byte array back into a String.
 
Carey Brown
Saloon Keeper
Posts: 4101
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alternatively you can wrap you input/output streams in object streams and use serialization to send and receive.
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow so much undeserving feedback. Thank you all guys. After reading all of your posts I decided that it is probably best to do as one of you suggested and
first get a working client and server that do not send int values but rather convert to bytes and convert after they reach their destination and so on.
Here are my client and server, I will soon make a working GUI and only then try to merge the two. But first I have to solve this.
When I uncomment the commented parts, the server doesn't even receive the numbers. This is odd. If my commented code was wrong at least the part before it should still work
like it works when I comment it out.





 
Paul Clapham
Sheriff
Posts: 23491
46
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's a buffered stream, which means that some data will stay in a buffer and not be sent until you flush the stream.
 
Carey Brown
Saloon Keeper
Posts: 4101
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you are going to use readLine() to read the strings then you'll have to end the strings with a new-line.
 
Saloon Keeper
Posts: 4413
108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Carey Brown wrote:If you are going to use readLine() to read the strings then you'll have to end the strings with a new-line.


Indeed. For socket operations, it's important to understand this point: Don't println to a socket (a general issue, not just a Mac issue).
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Carey Brown wrote:If you are going to use readLine() to read the strings then you'll have to end the strings with a new-line.



I thought I did that by adding the \r\n bit to each string, am I doing it wrong?
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Clapham wrote:It's a buffered stream, which means that some data will stay in a buffer and not be sent until you flush the stream.


I will try to add that and see if it works.
 
Carey Brown
Saloon Keeper
Posts: 4101
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Amadeus Pan wrote:

Carey Brown wrote:If you are going to use readLine() to read the strings then you'll have to end the strings with a new-line.



I thought I did that by adding the \r\n bit to each string, am I doing it wrong?

Not these:
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Clapham wrote:It's a buffered stream, which means that some data will stay in a buffer and not be sent until you flush the stream.



Yes that was it. It works now. Thanks!
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok here is the working code of all 3 parts, server client and GUI. I just need to merge the client and GUI now.





 
Carey Brown
Saloon Keeper
Posts: 4101
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry about my last post, I missed that you had added "\r\n".

In this code you call flush() twice. You only need the 2nd one, it will push everything that's buffered (the content of both write()s) out to the socket.
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Carey Brown wrote:Sorry about my last post, I missed that you had added "\r\n".

In this code you call flush() twice. You only need the 2nd one, it will push everything that's buffered (the content of both write()s) out to the socket.



Thanks. I will delete the first one. I wasn't quite sure if that was the case but it's nice to know it works that way.
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here is the final thing. Server and calc remain the same, I just merged client and gui. But I get socket closed error.



I intend to clean up the code after getting it to work cause I know it still looks like a mess and I don't even check for obvious things like if the textfields are even
written to or if the input is even numbers.

 
Carey Brown
Saloon Keeper
Posts: 4101
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You have two try blocks. The first is a try with resources which establishes a socket connection. The second is in an Action method which is executed asynchronusly by the Swing Event Dispatch Thread.  Note that the first try block is done with by the time you get to setVisible() and would have already closed the socket before the action event occurs. Put the resources in the second try block instead.

Which means you don't really need the first try at all.
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Carey Brown wrote:You have two try blocks. The first is a try with resources which establishes a socket connection. The second is in an Action method which is executed asynchronusly by the Swing Event Dispatch Thread.  Note that the first try block is done with by the time you get to setVisible() and would have already closed the socket before the action event occurs. Put the resources in the second try block instead.

Which means you don't really need the first try at all.


like this? Spoiler alert I am doing it wrong.


 
Carey Brown
Saloon Keeper
Posts: 4101
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
setSize() and setVisibble() should have been left where they were.

Anonymous classes are confusing. You are defining an actionPerformed() method inside your main() method. Normally you'd think of your code executing sequentially but that is not the case with your actionPerformed() method, it is only executed when you click the button which will happen AFTER setVisible() is called.

This would be clearer if you had added the code in an inner class, e.g. ConfirmAction. Anonymous isn't wrong it just takes getting used to.
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Carey Brown wrote:setSize() and setVisibble() should have been left where they were.

Anonymous classes are confusing. You are defining an actionPerformed() method inside your main() method. Normally you'd think of your code executing sequentially but that is not the case with your actionPerformed() method, it is only executed when you click the button which will happen AFTER setVisible() is called.

This would be clearer if you had added the code in an inner class, e.g. ConfirmAction. Anonymous isn't wrong it just takes getting used to.



Oh I get it. In my code the frame is only visible if I click on the button, but I can't click on the button if the window doesn't pop up.
 
Amadeus Pan
Ranch Hand
Posts: 37
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes it works perfectly now. Thank you all!!
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!