Simple client/server advice (chat processing)

Hello.

I'm working on a chat server for a game that I'm developing, and currently I have been able to get the server to send and receive messages through telnet, and I am now working on giving it a GUI.

From the GUI, I can send messages but the DataInputStream seems to be confusing me. What I need to do is monitor the input stream to add text to the text area when a message is sent to the server. Because I don't want to have a while loop constantly running readLine, I would like to know how I can monitor the stream efficiently.

Is there a simple way to do this that I am missing?

By the way, here is the code I'm using to start the input stream: (it will be run from the init method on startup)

private DataInputStream input;

publicvoid startInputStream(){

// uses addLine method to add text to chat box

try{

input =new DataInputStream(client.getInputStream());

}

catch (IOException e){

System.out.println(e);

}

}

[1406 byte] By [timothyb89a] at [2007-11-26 19:30:51]
# 1

> Because I don't want to have a while loop constantly running readLine

Well, thats the way Client/Server programming is done. The readLine() method blocks waiting for input. So you need to create a separate Thread for the IO so you don't freeze the application waiting for IO.

Read the [url http://java.sun.com/docs/books/tutorial/]Custom Networking[/url] tutorial. The section on sockets should get you started.

camickra at 2007-7-9 22:00:28 > top of Java-index,Java Essentials,Java Programming...
# 2

Ok, another question...

The client closes the connection to the server after sending it's first message and that seems to be preventing the messages from being added to the text box. If not, then my variables aren't being initialized correctly (I don't like not being able to declare variables from try/catch if you want to use them later).

Here's the full code to my client. If you need the server code, I got it from http://www.acm.org/crossroads/xrds6-1/ovp61.html . Sorry about it's messiness but NetBeans doesn't exactly help with that :P (I did try to keep the connecting code in a somewhat logical order).

So I'm hoping some one will notice bad variable declaration or an obvious error?

/*

* chatWindow.java

*

* Created on February 21, 2007, 10:24 PM

*/

package mazerunner;

import java.io.DataInputStream;

import java.io.IOException;

import java.io.PrintStream;

import java.net.*;

/**

*

* @author timothyb89

*/

public class chatWindow extends javax.swing.JFrame {

/** Creates new form chatWindow */

public chatWindow() {

initComponents();

connect("na");

}

private void addLine(String text) {

String oldText = textField.getText();

String newText = oldText += text + "\n";

//sets new text

textField.setText(newText);

}

private Socket client;

public void connect(String user) {

// creates new socket, connects to server

try {

client = new Socket("timothyb89.homelinux.org", 4321);

}

catch (IOException ex) {

ex.printStackTrace();

}

}

private PrintStream output;

public void sendMessage(String text) {

// sends text to the server to broadcast to clients

try {

output = new PrintStream(client.getOutputStream());

output.print(text);

output.close();

}

catch (IOException e) {

System.out.println(e);

}

}

private DataInputStream input;

public void startInputStream() {

// uses addLine method to add text to chat box

try {

input = new DataInputStream(client.getInputStream());

}

catch (IOException e) {

System.out.println(e);

}

// monitors server for messages (if only there was a better way...)

String addText;

try {

while ((addText = input.readLine()) != null) {

addLine(addText);

//System.out.println("echo: " + in.readLine());

}

} catch (IOException ex) {

ex.printStackTrace();

}

}

private void initComponents() {

jScrollPane1 = new javax.swing.JScrollPane();

textField = new javax.swing.JTextArea();

textToSend = new javax.swing.JTextField();

jButton1 = new javax.swing.JButton();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

textField.setColumns(20);

textField.setRows(5);

jScrollPane1.setViewportView(textField);

textToSend.addKeyListener(new java.awt.event.KeyAdapter() {

public void keyPressed(java.awt.event.KeyEvent evt) {

textToSendKeyPressed(evt);

}

});

jButton1.setText("Send");

jButton1.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

jButton1ActionPerformed(evt);

}

});

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());

getContentPane().setLayout(layout);

layout.setHorizontalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(layout.createSequentialGroup()

.addContainerGap()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addComponent(textToSend, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)

.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)

.addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE))

.addContainerGap())

);

layout.setVerticalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(layout.createSequentialGroup()

.addContainerGap()

.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addComponent(textToSend, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addComponent(jButton1)

.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))

);

pack();

}

private void textToSendKeyPressed(java.awt.event.KeyEvent evt) {

// will implement sending on press of enter key (need key code for enter key)

}

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

sendMessage(textToSend.getText());

connect("na");

textToSend.setText("");

}

/**

* @param args the command line arguments

*/

public static void main(String args[]) {

java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {

new chatWindow().setVisible(true);

}

});

}

// Variables declaration - do not modify

private javax.swing.JButton jButton1;

private javax.swing.JScrollPane jScrollPane1;

private javax.swing.JTextArea textField;

private javax.swing.JTextField textToSend;

// End of variables declaration

}

And finally, about my having to connect() every time, my socket seems to close after sending a message and I think it could be interfering with my line listener.

EDIT: I realized that I never ran the startInputStream code thus it never ran, so I ran it and remembered I needed to be using a thread for it. And it was at that time that I realized that I couldn't access any variables from my chatWindow class in my thread class.

I seem to be efficiently managing to confuse myself...

timothyb89a at 2007-7-9 22:00:28 > top of Java-index,Java Essentials,Java Programming...
# 3
why does the client close that connection if it wants to get updates and be able to send more at some point?The very idea is to keep the connection open and keep polling it for data.
jwentinga at 2007-7-9 22:00:28 > top of Java-index,Java Essentials,Java Programming...
# 4

> why does the client close that connection if it wants

> to get updates and be able to send more at some

> point?

> The very idea is to keep the connection open and keep

> polling it for data.

I never coded in any connection close. The only thing that closes is my DataOutputStream and I wouldn't imagine that is why I have to connect() every time. (I reopen my DataOutputStream every time I call sendMessage() )

So why is it closing?

And how can I access my variables from a new thread?

timothyb89a at 2007-7-9 22:00:28 > top of Java-index,Java Essentials,Java Programming...