Connection is good, but Client & Server can't communicate

I have created a simple 1:1 chat application to practice the java.net package.

I know it's more efficient to split it to the Server version and the Client version, but I really wanted to do it this way =p

Here's how it works: run the app and create a server; then, run it again to connect to that server. Typing text in the TextField is supposed to show it to the other window.

I've tried this on my own machine (both server and client running on it), as well as some random person from the internet.

The results were that the connections are well-made but communication was impossible. I've tried (see the commented-out line towards the very end) creating the input stream from System.in, which worked perfectly!

So, I can only suppose that it's an issue with the input stream...

I have no idea, and I've been on this for 6 hours. I hope someone can help me! =)

Here is what I have, so far:

import java.io.*;

import java.net.*;

import java.awt.*;

import java.awt.event.*;

publicclass JChatextends Frame{

privatestaticfinallong serialVersionUID = 1337;

private RecvThreadrecvThread;

private ButtonbtnSend;

private TextAreatxtReceive;

private TextFieldtxtSend;

private PanelpanReceive;

private PanelpanSend;

private ServerSocketserverSocket;

private Socketsocket;

private PrintWriterout;

private BufferedReaderin;

privateintport;

private Stringaddr;

private JChatparent;

/* for input dialog */

privatebooleanisServer;

private DialogdlgInput;

private ButtonbtnSetServer;

private ButtonbtnConnect;

private TextFieldtxtAddress;

privateLabellblInfo;

private PanelpanButtons;

publicstaticvoid main(String[] args){

new JChat().setVisible(true);

}

public JChat(){

port = 1337;

initComponents();

initEvents();

dlgInput.setVisible(true);

}

privatevoid initComponents(){

parent=this;

btnSend=new Button("Send");

txtReceive=new TextArea();

txtSend=new TextField();

panReceive=new Panel();

panSend=new Panel();

txtSend.setColumns(53);

panReceive.add("Center", txtReceive);

panSend.add("West", txtSend);

panSend.add("East", btnSend);

this.add("Center", panReceive);

this.add("South", panSend);

this.pack();

this.setResizable(false);

/* for input dialog */

dlgInput=new Dialog(parent,"Connect to Server:",true);

btnSetServer=new Button("Create Server");

btnConnect=new Button("Connect to Address");

txtAddress=new TextField("localhost", 10);

panButtons=new Panel();

lblInfo=new Label("Connect or Create Server");

panButtons.add("West", btnConnect);

panButtons.add("East", btnSetServer);

dlgInput.add("North", lblInfo);

dlgInput.add("Center", txtAddress);

dlgInput.add("South", panButtons);

dlgInput.setSize(250, 110);

dlgInput.setResizable(false);

}

privatevoid initEvents(){

this.addWindowListener(new WindowAdapter(){

publicvoid windowClosing(WindowEvent evt){

System.exit(0);

}

});

btnSend.addActionListener(new ActionListener(){

publicvoid actionPerformed(ActionEvent evt){

String msgSend = txtSend.getText();

out.println(msgSend);

System.out.println("Sending: " + msgSend);

txtSend.setText("");

}

});

txtSend.addActionListener(new ActionListener(){

publicvoid actionPerformed(ActionEvent evt){

String msgSend = txtSend.getText();

out.println(msgSend);

System.out.println("Sending: " + msgSend);

txtSend.setText("");

}

});

/* for input dialog */

btnSetServer.addActionListener(new ActionListener(){

publicvoid actionPerformed(ActionEvent evt){

addr =null;

isServer =true;

dlgInput.setVisible(false);

recvThread =new RecvThread();

recvThread.start();

parent.setTitle("Server");

}

});

btnConnect.addActionListener(new ActionListener(){

publicvoid actionPerformed(ActionEvent evt){

addr = txtAddress.getText().trim();

isServer =false;

dlgInput.setVisible(false);

try{

socket =new Socket(addr, port);

recvThread =new RecvThread();

recvThread.start();

}catch(UnknownHostException uhx){

txtReceive.append(uhx.toString() +"\n");

}catch(IOException iox){

txtReceive.append(iox.toString() +"\n");

}

parent.setTitle("Client");

}

});

}

class RecvThreadextends Thread{

privateboolean receiveFlag;

public RecvThread(){

super();

receiveFlag =true;

}

publicvoid run(){

try{

if (isServer){

serverSocket =new ServerSocket(port);

txtReceive.append("Accepting Connections...\n");

socket = serverSocket.accept();

txtReceive.append("Connection Established: " + socket.toString() +"\n");

}else{

socket =new Socket(addr, port);

txtReceive.append("Connection Established: " + socket.toString() +"\n");

}

out =new PrintWriter(socket.getOutputStream(),true);

//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

in =new BufferedReader(new InputStreamReader(System.in));

txtReceive.append("Waiting for Messages...\n");

String msg;

while (receiveFlag){

msg = in.readLine();

if (msg !=null){

txtReceive.append(msg +"\n");

}

this.sleep(50);

}

}catch(IOException iox){

txtReceive.append(iox.toString() +"\n");

}catch(InterruptedException ix){

txtReceive.append(ix.toString() +"\n");

}

}

}

}

[11904 byte] By [choey2k5a] at [2007-11-27 7:06:53]
# 1

A number of suggestions.

1) Get rid of the Swing code. You don't need it to practice network programming.

2) Break the client and server into different pieces. I don't like the look of some of your variables or what this code is doing at all. For example having one socket variable which is set in multiple places.

3) The riun method looks extremely shady. Putting client and server code in the same method does not seem a good idea. Moreover I don't see where you ever read anything from a Socket.

cotton.ma at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...
# 2

1) I'm not using Swing at all... Would you explain what you just advised?

2) I know, it should be split... But that's more of a design choice than a solution. Socket is instantiated only once in the life of the program.

3) I will optimize the code if I complete a good portion of the program or if it will, in fact, fix the issue with the communication. Reading from a Socket is done in this line in the run() method:

msg = in.readLine();

I am still wondering why communication isn't working, when inputting from the console works.

choey2k5a at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...
# 3

> 1) I'm not using Swing at all... Would you explain

> what you just advised?

>

Okay awt. Get rid of the GUI.

> 2) I know, it should be split... But that's more of a

> design choice than a solution. Socket is instantiated

> only once in the life of the program.

>

Your threads are stepping on each other's variables. You have multiple threads but then you have one socket variable shared with both.

That's not too good.

cotton.ma at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...
# 4

while (receiveFlag)

{

msg = in.readLine();

if (msg != null) {

txtReceive.append(msg + "\n");

}

this.sleep(50);

}

the client server app is stuck untill the message is recieved.

IE(using two different classes for the client and server should fix the problem)

*If this is not the case, then let me know I was wrong, I only glanced at the code.*

xpyro_666xa at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...
# 5
> > Your threads are stepping on each other's variables.> You have multiple threads but then you have one> socket variable shared with both.The same goes for in and out.
cotton.ma at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...
# 6

I don't think that is a problem, because two instances of the program will be run.

Also, the app is not necessarily "stuck" until it receives something, because listening for incoming is threaded. I did what you suggested, though, but it did not work.

The following is the modified code (basically redundant thread code):

import java.io.*;

import java.net.*;

import java.awt.*;

import java.awt.event.*;

public class JChat1 extends Frame {

private static final long serialVersionUID = 1337;

private ServRecvThreadservRecvThread;

private CliRecvThreadcliRecvThread;

private ButtonbtnSend;

private TextAreatxtReceive;

private TextFieldtxtSend;

private PanelpanReceive;

private PanelpanSend;

private ServerSocketserverSocket;

private Socketsocket;

private PrintWriterout;

private BufferedReaderin;

private intport;

private Stringaddr;

private JChat1parent;

/* for input dialog */

private booleanisServer;

private DialogdlgInput;

private ButtonbtnSetServer;

private ButtonbtnConnect;

private TextFieldtxtAddress;

privateLabellblInfo;

private PanelpanButtons;

public static void main(String[] args) {

new JChat().setVisible(true);

}

public JChat1() {

port = 1337;

initComponents();

initEvents();

dlgInput.setVisible(true);

}

private void initComponents() {

parent= this;

btnSend= new Button("Send");

txtReceive= new TextArea();

txtSend= new TextField();

panReceive= new Panel();

panSend= new Panel();

txtSend.setColumns(53);

panReceive.add("Center", txtReceive);

panSend.add("West", txtSend);

panSend.add("East", btnSend);

this.add("Center", panReceive);

this.add("South", panSend);

this.pack();

this.setResizable(false);

/* for input dialog */

dlgInput= new Dialog(parent, "Connect to Server:", true);

btnSetServer= new Button("Create Server");

btnConnect= new Button("Connect to Address");

txtAddress= new TextField("localhost", 10);

panButtons= new Panel();

lblInfo= new Label("Connect or Create Server");

panButtons.add("West", btnConnect);

panButtons.add("East", btnSetServer);

dlgInput.add("North", lblInfo);

dlgInput.add("Center", txtAddress);

dlgInput.add("South", panButtons);

dlgInput.setSize(250, 110);

dlgInput.setResizable(false);

}

private void initEvents() {

this.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent evt) {

System.exit(0);

}

});

btnSend.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent evt) {

String msgSend = txtSend.getText();

out.println(msgSend);

System.out.println("Sending: " + msgSend);

txtSend.setText("");

}

});

txtSend.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent evt) {

String msgSend = txtSend.getText();

out.println(msgSend);

System.out.println("Sending: " + msgSend);

txtSend.setText("");

}

});

/* for input dialog */

btnSetServer.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent evt) {

addr = null;

isServer = true;

dlgInput.setVisible(false);

servRecvThread = new ServRecvThread();

servRecvThread.start();

parent.setTitle("Server");

}

});

btnConnect.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent evt) {

addr = txtAddress.getText().trim();

isServer = false;

dlgInput.setVisible(false);

try {

socket = new Socket(addr, port);

cliRecvThread = new CliRecvThread();

cliRecvThread.start();

} catch(UnknownHostException uhx) {

txtReceive.append(uhx.toString() + "\n");

} catch(IOException iox) {

txtReceive.append(iox.toString() + "\n");

}

parent.setTitle("Client");

}

});

}

class ServRecvThread extends Thread {

private boolean receiveFlag;

public ServRecvThread() {

super();

receiveFlag = true;

}

public void run() {

try {

serverSocket = new ServerSocket(port);

txtReceive.append("Accepting Connections...\n");

socket = serverSocket.accept();

txtReceive.append("Connection Established: " + socket.toString() + "\n");

out = new PrintWriter(socket.getOutputStream(), true);

//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

in = new BufferedReader(new InputStreamReader(System.in));

txtReceive.append("Waiting for Messages...\n");

String msg;

while (receiveFlag) {

msg = in.readLine();

if (msg != null) {

txtReceive.append(msg + "\n");

}

this.sleep(50);

}

} catch(IOException iox) {

txtReceive.append(iox.toString() + "\n");

} catch(InterruptedException ix) {

txtReceive.append(ix.toString() + "\n");

}

}

}

class CliRecvThread extends Thread {

private boolean receiveFlag;

public CliRecvThread() {

super();

receiveFlag = true;

}

public void run() {

try {

socket = new Socket(addr, port);

txtReceive.append("Connection Established: " + socket.toString() + "\n");

out = new PrintWriter(socket.getOutputStream(), true);

//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

in = new BufferedReader(new InputStreamReader(System.in));

txtReceive.append("Waiting for Messages...\n");

String msg;

while (receiveFlag) {

msg = in.readLine();

if (msg != null) {

txtReceive.append(msg + "\n");

}

this.sleep(50);

}

} catch(IOException iox) {

txtReceive.append(iox.toString() + "\n");

} catch(InterruptedException ix) {

txtReceive.append(ix.toString() + "\n");

}

}

}

}

choey2k5a at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...
# 7

>> Your threads are stepping on each other's variables.

>> You have multiple threads but then you have one

>> socket variable shared with both.

>The same goes for in and out.

How do they step on each other's variables?

Two instances of the app are run; therefore, there will be two unshared objects.

EDIT:

Alright, I just created two console apps: a server and a client.

They are communicating well. I have no idea why it didn't work on the one I posted... Maybe you guys were right in that having the server and the client together was conflicting. I'm going to try to start the GUI app from scratch. I might split them into two apps, if it doesn't work out, again.

Message was edited by:

choey2k5

choey2k5a at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...
# 8

It was because I created a new Socket when the user clicks on the Connect button, and then again when the listener thread was made.

I got rid of the one in the thread, and all is well.

I had to go through creating two separate server and client apps to see that...

Thanks for telling me that Socet is being "set in multiple places", but a more descriptive pointer would've saved me 6 hours =(

choey2k5a at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...
# 9
Why? What's the problem with understanding 'set in two places'? A couple of minutes looking for 'new Socket' and/or trying to understand what you were being told and you could have saved the six hours.
ejpa at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...
# 10
Bah. Never mind...
choey2k5a at 2007-7-12 18:58:11 > top of Java-index,Core,Core APIs...