Need help with chat client
Author |
Message |
Asok

|
Posted: Fri May 20, 2005 9:19 pm Post subject: Need help with chat client |
|
|
Hey everyone. I'm trying to modify the code in the networking tutorial (found here http://www.compsci.ca/v2/viewtopic.php?t=8087 ) so that it operates more like a chat client. The main change is basically that the text string input is being passed in from a TextField and the output is being passed out on a TextArea (java.awt.applet).
The problem I'm encountering is that the server will only accept incoming information once and then drop the client. How should I go about making the server *always* accept information from the client?
Any help is greatly appreciated,
Thanks
-Asok |
|
|
|
|
 |
Sponsor Sponsor

|
|
 |
rizzix
|
Posted: Fri May 20, 2005 11:18 pm Post subject: (No subject) |
|
|
for the client it should be something along the lines: Java: | import java.net.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.*;
import java.io.*;
public class JTestClient {
public static void main (String[] args ) {
try {
final JFrame frame = new JFrame("JTestClient");
final Dimension screenSize = frame. getToolkit(). getScreenSize();
final String addr = args. length == 0 ? "localhost" : args [0];
final Socket server = new Socket(addr, 5060);
final PrintWriter serverOut = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(server. getOutputStream())
)
);
// message model of our chat client
class MessageListModel extends AbstractListModel {
final Vector<String> messages = new Vector<String> ();
public void addMessage (String msg ) {
messages. addElement(msg );
final int lastIndex = messages. size() - 1;
fireIntervalAdded (this, lastIndex, lastIndex );
}
public int getSize () {
return messages. size();
}
public String getElementAt (int index ) {
return messages. elementAt(index );
}
};
final MessageListModel msgListModel = new MessageListModel ();
frame. add(BorderLayout. CENTER,
new JScrollPane(new JList(msgListModel )));
final JTextArea jtaMessageInput = new JTextArea();
jtaMessageInput. addKeyListener(
new KeyAdapter() {
public void keyTyped (KeyEvent e ) {
if (e. getKeyChar() == KeyEvent. VK_ENTER) {
String msg = jtaMessageInput. getText();
msg = msg. substring(0, msg. length()- 1);
msgListModel. addMessage(msg );
serverOut. println(msg );
serverOut. flush();
jtaMessageInput. setText("");
}
}
}
);
jtaMessageInput. setBorder(BorderFactory. createEtchedBorder());
frame. add(BorderLayout. SOUTH, jtaMessageInput );
// close connection upon exit
frame. addWindowListener(
new WindowAdapter() {
public void windowClosing (WindowEvent we ) {
try {
server. close();
} catch (Exception e ) {
System. err. println(e );
}
}
}
);
frame. setBounds(screenSize. width/ 4, screenSize. height/ 4,
screenSize. width/ 2, screenSize. height/ 2);
frame. setDefaultCloseOperation(JFrame. EXIT_ON_CLOSE);
frame. setVisible(true);
jtaMessageInput. requestFocus();
} catch (Exception e ) {
System. err. println(e );
}
}
} |
PS: this is very very bad design.. but it does explain some concepts such as separating the Model (MessageListModel) and Controller (KeyAdapter) from the View (JTextArea)
PPS: this code only covers sending messages (not recieving them) |
|
|
|
|
 |
Asok

|
Posted: Sat May 21, 2005 3:05 pm Post subject: (No subject) |
|
|
wow rizzix, thank you so much however the code doesn't seem to run, error is on this line:
Vector<String> messages = new Vector<String>();
and it is "generics not supported in -source 1.2(try source 1.5 to enable generics)" the editor I'm using is JBuilder 2005 Personal.
anyways I thought that it might help if I post my client code here so you can get a sense of what I'm *trying* to do (it interfaces with your server code left unchanged from the tutorial, this build in particular cannot properly send or recieve messages from the server yet but it can connect)
Java: | import java.applet.Applet;
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
public class ClientApplet extends WindowAdapter implements ActionListener, ItemListener
{
Frame frmMenu = new Frame("Chat Client");
TextArea txaOutput = new TextArea(25, 70);
TextField txtInput = new TextField(62);
Button btnSend = new Button("Send");
Panel pnlInterface = new Panel();
String strInput;
String strServer = new String("localhost");
int intPort = 5060;
boolean blnConnect = false;
//Menu components
MenuBar mnuMain = new MenuBar();
Menu mnuFile = new Menu("File");
Menu mnuOptions = new Menu("Options");
Menu mnuOptionsFontColor = new Menu("Font Color");
//Menu items
MenuItem mnuFileConnect = new MenuItem("Connect");
MenuItem mnuFileExit = new MenuItem("Exit");
CheckboxMenuItem mnuOptionsFontColorBlack = new CheckboxMenuItem("Black", true);
//class ClientApplet {
public static void main (String[] args )
{
ClientApplet myClientApp = new ClientApplet ();
myClientApp. designLayout();
myClientApp. createInterface();
}
public void createInterface ()
{
//Create the Menu Bar
//File Menu
mnuMain. add(mnuFile );
mnuFile. addActionListener(this);
mnuFile. add(mnuFileConnect );
mnuFile. addSeparator();
mnuFile. add(mnuFileExit );
//Options Menu
mnuMain. add(mnuOptions );
mnuOptions. addActionListener(this);
mnuOptions. add(mnuOptionsFontColor );
mnuOptionsFontColor. addActionListener(this);
mnuOptionsFontColor. add(mnuOptionsFontColorBlack );
mnuOptionsFontColorBlack. addItemListener(this);
//Attach the menu bar to the frame
frmMenu. setMenuBar(mnuMain );
//Set up the components and the frame
txaOutput. setForeground(Color. black);
txtInput. setForeground(Color. black);
txtInput. requestFocus();
txaOutput. setEditable(false);
frmMenu. add(pnlInterface );
frmMenu. addWindowListener(this);
frmMenu. setSize(600, 500);
frmMenu. show();
}
public void actionPerformed (ActionEvent evt )
{
//Determine which menu item was selected
String strMenuItem = evt. getActionCommand();
//Determine the object calling this method
Object objSource = evt. getSource();
if (strMenuItem. equals("Exit")) {
System. exit(0);
}
else if (strMenuItem. equals("Connect")) {
//Source Code Credit: Rizzix of CompSci.ca. Tutorial available publically here: http://www.compsci.ca/v2/viewtopic.php?t=8087
try {
String input = txtInput. getText();
BufferedReader in = new BufferedReader(
new InputStreamReader(System. in));
// establish connection to server
txaOutput. append("Attempting to connect to: " + strServer + " (" + intPort + ")" + "\n");
Socket server = new Socket(strServer, intPort );
// establish an output stream with server
PrintWriter serverOut = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(server. getOutputStream())
)
);
// write Strings to server
//while (!(input = in.readLine()).equals("__END__")) {
// serverOut.println(input);
// serverOut.flush();
// }
if (objSource == txtInput || objSource == btnSend ) {
strInput = txtInput. getText();
serverOut. println(strInput );
serverOut. flush();
txtInput. setText("");
txtInput. requestFocus();
}
// server.close(); // close connection
}
catch (Exception e ) {
//System.out.println(e);
txaOutput. append("Error: " + e + "\n");
blnConnect = false;
}
}
}
public void itemStateChanged (ItemEvent evt )
{
//Determine the state of checkbox menu item
int intState = evt. getStateChange();
}
public void windowClosing (WindowEvent evt )
{
//Exit to the operating system
System. exit(0);
}
public void designLayout ()
{
pnlInterface. setLayout(new FlowLayout());
pnlInterface. add(txaOutput );
pnlInterface. add(txtInput );
pnlInterface. add(btnSend );
txtInput. addActionListener(this);
btnSend. addActionListener(this);
}
}
|
Anyways I'd just like to thank you again for your help, I was never expecting so much  |
|
|
|
|
 |
Hikaru79
|
Posted: Sat May 21, 2005 3:53 pm Post subject: (No subject) |
|
|
Asok wrote: wow rizzix, thank you so much however the code doesn't seem to run, error is on this line:
Vector<String> messages = new Vector<String>();
and it is "generics not supported in -source 1.2(try source 1.5 to enable generics)" the editor I'm using is JBuilder 2005 Personal.
The problem is that you're using an outdated version of java (1.2) when we are several years ahead of that (1.5). You can get the newest SDK from http://java.sun.com |
|
|
|
|
 |
rizzix
|
Posted: Sat May 21, 2005 11:27 pm Post subject: (No subject) |
|
|
asok the problem with your code is that your are establishing a connection to the server every time an action is performed.. you might want to move that snippet up.. i.e keep the connection open.. and simply send a message to the server when an action is performed..
also,, close your connection when the windows is closed (look at my snippet on how to do that)
anyways.. i've updated my code to actually send a message. to test it out (after you compile it).. just make sure you first run TestServer (from tutorial) and then run this program.. simple as that. |
|
|
|
|
 |
Asok

|
Posted: Sun May 22, 2005 12:52 am Post subject: (No subject) |
|
|
hey rizzix
I figured out why I was only able to ever send one message. It had to do with the: while ((input = clientIn.readLine()) != null) on the server side.
I got rid of that and can now send as many messages as I want to the server
I basically now have only 3 more issues to tackle:
1) getting the server to send it back to display it in the text area. I assume it's the same way as I sent data to the server from the client. But it's 1:40 AM and I'll test that in the morning
2) modifying the server code to allow multiple clients on at the same time. This will probably be the trickiest part because it'll require an overhaul of the server code(flexible array of clients perhaps?) and I'll wait till after I get one client working flawlessly before I attempt to modify the server code more.
3) correcting a bloody EOF error when trying to read a file. (your tutorial helped me out a lot with the concepts of I/O ) basically I'm using a single object (user) to store everything I need. so the file simply contains a writeObject. the problem is I keep getting the EOF error when trying to read from that file. The code for that class is posted below, I'm pretty sure it's correct but something is getting messed up to cause the reading to go nuts.
code: |
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class MsgPreferences extends Dialog implements ActionListener
{
//Create components
Button btnSave = new Button("Save Preferences");
Button btnCancel = new Button("Cancel");
TextField txtName = new TextField(25);
TextField txtPort = new TextField(10);
TextField txtServer = new TextField(25);
Label lblError = new Label(" ");
private String strServer;
private String strName;
private String strPort;
//Declare Stream objects
FileOutputStream outputData; //Stream to create file
FileInputStream inputData; //Stream to read from a file
ObjectOutput objSaveData; //Stream to save an object
ObjectInputStream objGetData; //Stream to retrieve an object
//Constructor
public MsgPreferences (Frame frmParent)
{
//Call the parent's constructor
super(frmParent, "Preferences" ,true);
//Set up the Dialog box
Panel pnlLayout = new Panel();
pnlLayout.setLayout(new FlowLayout());
pnlLayout.add(new Label("Username: "));
pnlLayout.add(txtName);
pnlLayout.add(new Label("Server: "));
pnlLayout.add(txtServer);
pnlLayout.add(new Label(" Port:"));
pnlLayout.add(txtPort);
pnlLayout.add(btnSave);
pnlLayout.add(btnCancel);
pnlLayout.add(lblError);
add(pnlLayout);
btnSave.addActionListener(this);
btnCancel.addActionListener(this);
//Listen for close box
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent evt)
{
closeStream();
dispose(); //Destroy the dialog
}
});
openStream();
readFile();
setSize(300,200);
setLocation(200,200);
show();
}
public void openStream()
{
try
{
//Create file and object output streams
outputData = new FileOutputStream("user.txt");
objSaveData = new ObjectOutputStream(outputData);
//Create file and object input streams
inputData = new FileInputStream("user.txt");
objGetData = new ObjectInputStream(inputData);
lblError.setText(" File Opened ");
}
catch (Exception error)
{
lblError.setText("Error Opening File");
}
}
public void readFile()
{
try
{
User userCurrent;
userCurrent = (User) objGetData.readObject();
txtName.setText(userCurrent.getName());
txtServer.setText(userCurrent.getServer());
txtPort.setText(userCurrent.getPort());
}
catch (EOFException eof)
{
lblError.setText("End of File");
}
catch (Exception error)
{
lblError.setText("Error Reading File");
}
}
public void closeStream()
{
try
{
objSaveData.close(); //Close the object output stream
outputData.close(); //Close the file output stream
objGetData.close(); //Close the object input stream
inputData.close(); //Close the file input stream
}
catch (IOException error)
{
lblError.setText("Error closing file");
}
}
public void actionPerformed(ActionEvent evt)
{
//Determine the object calling this method
Object objSource = evt.getSource();
if (objSource == btnSave) {
try {
//int intPort = Integer.valueOf(txtPort.getText()).intValue();
User newUser = new User(txtName.getText(), txtServer.getText(),
txtPort.getText());
objSaveData.writeObject(newUser);
strServer = txtServer.getText();
strName = txtName.getText();
strPort = txtPort.getText();
//objSaveData.writeUTF(txtName.getText());
//objSaveData.writeUTF(txtServer.getText());
//objSaveData.writeUTF(txtPort.getText());
objSaveData.flush();
lblError.setText("User Saved");
}
catch (Exception error) {
lblError.setText("Error writing to file");
}
}
if (objSource == btnCancel)
{
closeStream();
dispose(); //Destroy the dialog when Cancel button is pressed
}
}
public String setUserName()
{
return strName;
}
public String setServer()
{
return strServer;
}
public String setPort()
{
return strPort;
}
}
|
rizzix, I can't thank you enough, your tutorials have been basically the key to understanding all of this (my textbook is terrible haha ) |
|
|
|
|
 |
rizzix
|
Posted: Sun May 22, 2005 1:32 am Post subject: (No subject) |
|
|
does the User class implement the Serializable interface? it should.. this interface does not define any methods as such.. it simply acts as a flag explictly stating that objects of that class can be serialized (read or written to a stream). |
|
|
|
|
 |
Asok

|
Posted: Sun May 22, 2005 10:32 am Post subject: (No subject) |
|
|
yea it does rizzix, here's my user class
code: |
import java.io.*;
public class User implements Serializable
{
private String strName;
private String strServer;
private String strPort;
//class constructor
User(String strNameIn, String strServerIn, String strPortIn)
{
strName = strNameIn;
strServer = strServerIn;
strPort = strPortIn;
}
public String getName()
{
//Retrieve user name
return strName;
}
public String getServer()
{
//Retrieve server IP/Hostname
return strServer;
}
public String getPort()
{
//Retrieve server port
return strPort;
}
|
I'm still trying to figure out why there is the EOF error, it says there is no problem writing only reading but that may not be the actual case. |
|
|
|
|
 |
Sponsor Sponsor

|
|
 |
rizzix
|
Posted: Sun May 22, 2005 1:41 pm Post subject: (No subject) |
|
|
heh you sure there's something in that file? cuz ur code: first trys to read from the file.. then when an action is performed.. it writes to the file..
so yea.. you might want to write a dummy object to that file first and then run ur code.. |
|
|
|
|
 |
Asok

|
Posted: Sun May 22, 2005 2:33 pm Post subject: (No subject) |
|
|
when I open the text file all I get is two box characters
so I know SOMETHING is in there but I'm not exactly sure what. |
|
|
|
|
 |
rizzix
|
Posted: Sun May 22, 2005 5:24 pm Post subject: (No subject) |
|
|
hmm.. well.. empty the file.. and write a dummy object to it.. then run ur program.. post if you still have errors. |
|
|
|
|
 |
Asok

|
Posted: Sun May 22, 2005 10:20 pm Post subject: (No subject) |
|
|
thanks for the advice rizzix! now that txt file isn't empty because I'm writng the dummy object. the text file looks like this:
Quote:
¬à sr User}×j-d ÇQ L strNamet Ljava/lang/String;L strPortq ~ L strServerq ~ xpt Guestt 5060t localhost
the problem now is on the reading side. when I close and reopen it only displays the information in the dummy object. I think it has something to do with the logical aspect of my code. I've posted the updated code here:
code: |
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class MsgPreferences extends Dialog implements ActionListener
{
//Create components
Button btnSave = new Button("Save Preferences");
Button btnCancel = new Button("Cancel");
TextField txtName = new TextField(25);
TextField txtPort = new TextField(10);
TextField txtServer = new TextField(25);
Label lblError = new Label(" ");
private String strServer = "localhost";
private String strName = "Guest";
private String strPort = "5060";
//Declare Stream objects
FileOutputStream outputData; //Stream to create file
FileInputStream inputData; //Stream to read from a file
ObjectOutput objSaveData; //Stream to save an object
ObjectInputStream objGetData; //Stream to retrieve an object
//Constructor
public MsgPreferences (Frame frmParent)
{
//Call the parent's constructor
super(frmParent, "Preferences" ,true);
//Set up the Dialog box
Panel pnlLayout = new Panel();
pnlLayout.setLayout(new FlowLayout());
pnlLayout.add(new Label("Username: "));
pnlLayout.add(txtName);
txtName.setText(strName);
pnlLayout.add(new Label("Server: "));
pnlLayout.add(txtServer);
txtServer.setText(strServer);
pnlLayout.add(new Label(" Port:"));
pnlLayout.add(txtPort);
txtPort.setText(strPort);
pnlLayout.add(btnSave);
pnlLayout.add(btnCancel);
pnlLayout.add(lblError);
add(pnlLayout);
btnSave.addActionListener(this);
btnCancel.addActionListener(this);
//Listen for close box
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent evt)
{
closeStream();
dispose(); //Destroy the dialog
}
});
openStream();
//write dummy object
try {
//int intPort = Integer.valueOf(txtPort.getText()).intValue();
User newUser = new User(txtName.getText(), txtServer.getText(),
txtPort.getText());
objSaveData.writeObject(newUser);
strServer = txtServer.getText();
strName = txtName.getText();
strPort = txtPort.getText();
//objSaveData.writeUTF(txtName.getText());
//objSaveData.writeUTF(txtServer.getText());
//objSaveData.writeUTF(txtPort.getText());
objSaveData.flush();
lblError.setText("User Saved");
}
catch (Exception error) {
lblError.setText("Error writing to file");
}
readFile();
setSize(300,200);
setLocation(200,200);
show();
}
public void openStream()
{
try
{
//Create file and object output streams
outputData = new FileOutputStream("user.txt");
objSaveData = new ObjectOutputStream(outputData);
//Create file and object input streams
inputData = new FileInputStream("user.txt");
objGetData = new ObjectInputStream(inputData);
lblError.setText(" File Opened ");
}
catch (Exception error)
{
lblError.setText("Error Opening File");
}
}
public void readFile()
{
try
{
User userCurrent;
userCurrent = (User) objGetData.readObject();
txtName.setText(userCurrent.getName());
txtServer.setText(userCurrent.getServer());
txtPort.setText(userCurrent.getPort());
}
catch (EOFException eof)
{
lblError.setText("End of File");
}
catch (Exception error)
{
lblError.setText("Error Reading File");
}
}
public void closeStream()
{
try
{
objSaveData.close(); //Close the object output stream
outputData.close(); //Close the file output stream
objGetData.close(); //Close the object input stream
inputData.close(); //Close the file input stream
}
catch (IOException error)
{
lblError.setText("Error closing file");
}
}
public void actionPerformed(ActionEvent evt)
{
//Determine the object calling this method
Object objSource = evt.getSource();
if (objSource == btnSave) {
try {
//int intPort = Integer.valueOf(txtPort.getText()).intValue();
User newUser = new User(txtName.getText(), txtServer.getText(),
txtPort.getText());
objSaveData.writeObject(newUser);
strServer = txtServer.getText();
strName = txtName.getText();
strPort = txtPort.getText();
//objSaveData.writeUTF(txtName.getText());
//objSaveData.writeUTF(txtServer.getText());
//objSaveData.writeUTF(txtPort.getText());
objSaveData.flush();
lblError.setText("User Saved");
}
catch (Exception error) {
lblError.setText("Error writing to file");
}
}
if (objSource == btnCancel)
{
closeStream();
dispose(); //Destroy the dialog when Cancel button is pressed
}
}
public String setUserName()
{
return strName;
}
public String setServer()
{
return strServer;
}
public String setPort()
{
return strPort;
}
}
|
Thanks again for all of your help rizzix  |
|
|
|
|
 |
rizzix
|
Posted: Sat May 28, 2005 7:25 pm Post subject: (No subject) |
|
|
ok its really simple.. and yes its a logic problem..
first delete the user.txt file.
now edit your code to check to see if user.txt exists.. if it does not exist.. write a dummy object to the file..
that will fix your problems.. btw in order to check if the file exist. you'd have to first create a File object. |
|
|
|
|
 |
|
|