I have implemented a chat client. And as of now it only fully works in cmd, because I can't figure out how I'm supposed to implement the send button in the chat client GUI.
So this is my chat client class:
class ChatClientClass {
private String host;
private int port;
private Socket socket;
private PrintWriter out;
private BufferedReader in;
private BufferedReader stdIn;
ChatWindow chatWindow = new ChatWindow();
public ChatClientClass(String host, int port) {
try {
this.socket = new Socket(host, port);
this.out =
new PrintWriter(socket.getOutputStream(), true);
this.in =
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
this.stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
chatWindow.addText("You: " + userInput);
String serverMessage = in.readLine();
chatWindow.addText(serverMessage);
}
} catch (UnknownHostException e) {
System.err.println("Couldn't not find host " + host);
e.printStackTrace();
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " + host);
e.printStackTrace();
System.exit(1);
}
}
}
As of now, I can only write stuff in the command prompt. But what I've written as well as what the server answers will appear in my GUI. The addText(String text)-method adds the input and the output to my GUI.
But I can't figure out how to implement my send button. An easy way would be if I could just send a reference to the PrintWriter and a reference to the GUI when I call the constructor of my ActionListener class, and just do something like: thePrintWriter.println( [get the value of the text area that belongs to the send button] ) in the public void actionPerformed(ActionEvent e)-method. But since I can't/shouldn't call the constructor of my ActionListener from my chat client class, hence sending those references. That wont be possible, right?
I also thought about making the PrintWriter variable static, and also making the JTextArea containing the message I want to send variable static, and then create static methods to access these two variables. But it just feels like I'm doing something terribly wrong when I'm doing that. And I can't get that to work either.
So how is a send button in a chat client supposed to be implemented?
Thanks in advance!
If you are new in GUI building in java/eclipse.
I suggest you the gui builder:
http://www.eclipse.org/windowbuilder/
Its really easy to use, and you can make simple GUI-for your app.
To your problem you will need a button to your frame, and you need to add an actionlistener than if you fire it you can do what you want.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class ButtonAction {
private static void createAndShowGUI() {
JFrame frame1 = new JFrame("JAVA");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton(" >> JavaProgrammingForums.com <<");
//Add action listener to button
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//Execute when button is pressed
//Here call your sender fucntion
out.println(userInput);
chatWindow.addText("You: " + userInput);
String serverMessage = your_jtext.getText();
chatWindow.addText(serverMessage);
System.out.println("You clicked the button");
}
});
frame1.getContentPane().add(button);
frame1.pack();
frame1.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Related
I am trying to implement a JButton that displays Connect or Disconnect depending on whether or not it is connected to the server. So, when I click the button when it says Connect, it'll connect to the server, and then it will show Disconnect. When I click Disconnect, it'll disconnect from the server and the button will show connect again. However, when I click the button, nothing happens.
btnConnect.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
if (btnConnect.getText().equals("Connect")){
btnConnect.setText("Disconnect");
try {
int portNum = 5520;
String hostAddress = Actual_IP_Address.getText();
sock = new Socket(hostAddress, portNum);
writeSock = new PrintWriter ( sock.getOutputStream(), true);
readSock = new BufferedReader (new InputStreamReader(sock.getInputStream()));
}
catch(Exception ex) {
System.out.println("Error: " + ex);
sock = null;
}
}
if (btnConnect.getText().equals("Disconnect")){
btnConnect.setText("Connect");
try {
readSock.close();
writeSock.close();
sock.close();
sock = null;
}
catch(Exception ex) {
System.out.println("Error: " + ex);
sock = null;
}
}
}}
);
How come when I click the button it merely shows Connect?
Right now, the basic outline of your code is
if (button.getText().equals("Connect"){
button.setText("Disconnect")
}
if (button.getText().equals("Disconnect"){
button.setText("Connect")
}
It looks like what is happening is that you are changing your button text value to "Disconnect" like you should be. But then immediately after, you once again check if the button text value is equal to "Disconnect" and change it again. Change your two if statements to be an else-if statement instead
if (button.getText().equals("Connect"){
button.setText("Disconnect")
} else if (button.getText().equals("Disconnect"){
button.setText("Connect")
}
This "basic" problem is, when connected, you set the button text to Disconnect and then promptly check to see if the text is Disconnect and set it back to Connect.
The larger problem is you're coupling your code, which will make it hard to manage and keep the UI in sync with what is actually going on - what happens if the socket disconnects unexpectedly.
Another issue is, you're potentially, blocking the UI, which cause it to "freeze" and become unresponsive, as it might take a few seconds for the socket to establish.
A better solution would be to try and decouple the UI from the socket and rely on some kind of observer pattern so you could be notified when the socket state changes, regardless of whether the UI stopped the socket or it stopped due to some other condition.
Personally, I'd use a SwingWorker for this, as it allows you to overload long running/blocking operations to another thread, but provides a number of useful mechanisms for delivering updates back to the UI thread (ie the Event Dispatching Thread) safely, for example...
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JButton doStuff;
private SocketWorker worker;
public TestPane() {
setLayout(new GridBagLayout());
doStuff = new JButton("Connect");
doStuff.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if (worker == null) {
doStuff.setText("...");
worker = new SocketWorker("hostname");
worker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("state".equals(evt.getPropertyName())) {
System.out.println(worker.getState());
switch (worker.getState()) {
case STARTED:
doStuff.setText("Disconnect");
break;
case DONE:
worker = null;
doStuff.setText("Connect");
break;
}
}
}
});
worker.execute();
} else {
System.out.println("...");
try {
worker.stop();
} catch (IOException ex) {
ex.printStackTrace();
}
doStuff.setText("Connect");
}
}
});
add(doStuff);
}
}
public class SocketWorker extends SwingWorker<Void, Void> {
private Socket socket;
private String hostName;
private PrintWriter writeSock;
private BufferedReader readSock;
public SocketWorker(String hostName) {
this.hostName = hostName;
}
#Override
protected Void doInBackground() throws Exception {
// This is just here to demonstrate the point
Thread.sleep(5000);
//int portNum = 5520;
//socket = new Socket(hostName, portNum);
//writeSock = new PrintWriter(socket.getOutputStream(), true);
//readSock = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Do your socket handling here...
return null;
}
public void stop() throws IOException {
if (socket == null) { return; }
socket.close();
}
}
}
In this example, I've just used Thread.sleep to put a "mocked" operation in place. I'd consider doing all your reading/writing to the socket through the worker and keep it alive until the socket it closed (for what ever reason). But, this will demonstrate how the button can be updated no based on the state of the click, but based on the state of the worker itself
Take a look at Worker Threads and SwingWorker and Concurrency in Swing for more details
I'm trying to create a text chat with Java. I have a Server and a Client that connect to each other using Streams, and send data using the objectInputStream and objectOutputStream.
I have GUI's for both the client and the server.
I made these GUI's using intellij's GUI Form.
server GUI form image
The problem I'm having is when I try to display text to the GUI of the server. I can append to the GUi if I call my relayToAll method from the JTextField actionlistener, which then send the message to all the clients and prints it out in the servers GUI.
If i try to call the same method from where I receive the input, then the append to the text area does not work.
Can anyone tell me why its not appending?
Thanks
public class ServerTest {
private JTextField textField1;
private JTextArea textArea1;
private JPanel Panel;
static private ObjectOutputStream objectOutputStream;
static private ObjectInputStream objectInputStream;
static private Socket client;
static private ArrayList<Socket> clients = new ArrayList<Socket>();
static private ArrayList<ObjectOutputStream> objectOutputStreams = new ArrayList<>();
public void relayToAll(String message){
try {
for(int i = 0; i < clients.size(); i++) {
ObjectOutputStream output = objectOutputStreams.get(i);
output.writeObject(message);
output.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
appendTextArea(message);
}
public void appendTextArea(String text){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println("This should go to the Server GUI: " + text);
textArea1.append(text + "\n");
}
});
}
public ServerTest() {
textField1.addActionListener(e -> {
System.out.println(e.getActionCommand());
relayToAll(e.getActionCommand());
textField1.setText("");
});
}
public void ReadInput(ObjectInputStream input, int port){
try {
String oldMessage = "";
while (true) {
String message = (String) input.readObject();
if (message != oldMessage){
System.out.println(port + ": " + message);
oldMessage = message;
relayToAll(port + ": " + message);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void IOSetup(){
try {
ServerSocket serverSocket = new ServerSocket( 6969 );
ExecutorService executor = Executors.newFixedThreadPool(5);
System.out.println("server on\n");
for (int i = 0; i < 5; i++){
client = serverSocket.accept();
clients.add(client);
System.out.println("Connection from: "+ client.getPort());
objectOutputStream = new ObjectOutputStream(client.getOutputStream());
objectOutputStreams.add(objectOutputStream);
objectInputStream = new ObjectInputStream(clients.get(i).getInputStream());
executor.submit(() -> {
ReadInput(objectInputStream, client.getPort());
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Server");
frame.setContentPane(new ServerTest().Panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ServerTest application = new ServerTest();
application.IOSetup();
}
Actually you've got kind of a silly mistake. Please check lines (A) and (B) below:
public static void main(String[] args) {
JFrame frame = new JFrame("Server");
frame.setContentPane(new ServerTest().Panel); // *************** (A)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ServerTest application = new ServerTest(); // *************** (B)
application.IOSetup();
}
Do you see a problem? You're creating TWO ServerTest objects, one that has its Panel variable added to the JFrame and that gets displayed, and the other that is set up for IO communication. The ActionListener changes the state of the displayed JTextArea while the IO communications changes the state of a JTextArea that is in the second ServerTest instance, the one not displayed.
One improvement is to create only one instance:
public static void main(String[] args) {
ServerTest application = new ServerTest(); // create one instance
JFrame frame = new JFrame("Server");
// frame.setContentPane(new ServerTest().Panel);
frame.setContentPane(application.Panel); // and use in both places
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
//ServerTest application = new ServerTest();
application.IOSetup(); // and use in both places
}
Other problems:
You've got long-running code long running and blocking in a background thread, and that is potentially dangerous, and the only reason that your GUI is not getting frozen is because you're starting the GUI (incorrectly) on the main thread and off of the Swing event thread. For more on this, you will want to read up on Swing concurrency: Lesson: Concurrency in Swing
You will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
Currently developing a GUI in Java that communicates through Ethernet. It is designed to send data through one port and receive data through the other. The data received is used to populate a dynamic section of the GUI that changes with the data received that unfortunately must also be scaled to fit on the screen. My question is how using Java would I go about populating part of the GUI with a scaled version of the Ethernet data received?
Using swing for the display and awt for the listener. Data is received from java socket. Still unclear on exact way received data is packaged but trying to get a base idea on how to populate the virtual screen. separate thread to populate the screen most likely but also how to actually populate the screen with scaled version.
The GUI is designed to emulate a physical display unit with physical buttons and graphical display (colored words as well as arrows and other graphics, original idea was to just map it pixel for pixel but scaling throws me off).
Here is a snippet of the code, the virtual screen is not populated at the moment, just white outline and the communication port is not opened yet (all McduPanel does is paint static image to the screen, and setKey just sets a String variable based on the button pressed and sends it through the open port):
private McduPanel mPanel;
public McduGui() {
mPanel = new McduPanel();
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice vc = env.getDefaultScreenDevice();
JFrame window = new JFrame();
window.addMouseListener(new MouseClickHandler());
window.add(mPanel);
window.setUndecorated(true);
window.setResizable(false);
vc.setFullScreenWindow(window);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
getPorts();
} catch (IOException ex) {
System.out.println(ex);
}
}
public static class MouseClickHandler implements MouseListener {
#Override
public void mousePressed(MouseEvent me) {
int screenX = me.getXOnScreen();
int screenY = me.getYOnScreen();
System.out.println("screen(X,Y) = " + screenX + "," + screenY);
setKey(screenX,screenY);
}
#Override
public void mouseReleased(MouseEvent e) {
}
#OverrideDo
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
public static void getPorts() throws IOException {
String screen = "host"; //host name
String charData = "host"; //host name
int screenPort = 71;//Integer.parseInt(71);
int charPort = 72;//port number
Socket echoSocket = new Socket(screen, 71);
PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
}
To further clarify:
A static image is painted to the screen with Strings mapped to positions on the screen that will send the String associated to that position every time it sees a mouse press. There is a virtual screen within the GUI that will change based on data received from port. It is up in the air what that data will be right now, but by design it is supposed to be the exact same as what physical screen looks like.
Best example I can give is think of a gameboy, the gameboy image is static on the panel, but virtual screen keeps updating based on the data received from the port. That box needs to be refreshed and more than likely scaled from the original size.
OK. I really tried hard to understand your problem. I am still not sure if your problem is painting, threads or reading from a socket, but I made a runnable example. The code is super ugly, but you can execute it as it is. The code create a "test server" which writes to a port every some seconds and a "test client" which reads from this port every some seconds. After the client read some text, it will print it on the screen.
Note that this is just an example - super ugly as I said, but it runs right out of the box. Also not that I strongly recommend to not paint any stuff! Use JButtons to display buttons and JTextFields (or JTextAreas) to display text. Do not print it by painting on the screen!
import java.awt.Graphics;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class RemoteConsole extends JPanel {
private String text = "Start";
public static void main(String[] args) throws Exception {
// your class is called McduPanel
RemoteConsole remoteConsole = new RemoteConsole();
// JFrame which contains all components
JFrame frame = new JFrame();
frame.setSize(400, 500);
frame.setVisible(true);
frame.getContentPane().add(remoteConsole);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ServerSocket serverSocket = new ServerSocket(4564);
// this is a test server which just writes "test"
// to a port every 1 seconds
new Thread() {
public void run() {
try {
Socket socket = new Socket("localhost", 4564);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while (true) {
System.out.println("send");
out.println("test");
sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
// a test client which checks the port every 1.5 seconds
// and paints the text to a JPanel
new Thread() {
public void run() {
try {
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
String message = in.readLine();
System.out.println("received: " + message);
remoteConsole.appendText(message);
remoteConsole.repaint();
sleep(1500);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString(text, 75, 100);
}
public void appendText(String text) {
this.text += text;
}
}
hello friends i have created a UDP chatting program through which the clients can communicate over LAN.
I have created a genaralized program i.e. I run the same code with different port nos. and IP address when on LAN
My problem is that This code below works fine on localhost but when i try to connect two machines this code doesnt work..there is no error as of such but still the two clients cant communicate
I have also switched off the firewalls.But i am unable to find out why i cant communicate between two machines
The Code is as follows ::
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
class ChatApplDG extends Frame implements ActionListener
{
TextField tf = new TextField(50);
Button btn = new Button("Send");
Button exit = new Button("Exit");
TextArea ta = new TextArea(50,10);
int fromPort, toPort;
String hostName;
DatagramSocket dgSock;
public static void main(String args[]) throws Exception
{
ChatApplDG ca = new ChatApplDG();
ca.startClient(args[0],Integer.parseInt(args[1]),Integer.parseInt(args[2]));
}
ChatApplDG()
{
Panel p = new Panel();
add(p,BorderLayout.NORTH);
p.add(tf);
p.add(btn);
p.add(exit);
add(ta,BorderLayout.CENTER);
btn.addActionListener(this);
exit.addActionListener(this);
setSize(500,300);
show();
ta.setEditable(false);
}
void startClient(String hName,int fPort,int tPort)
{
try
{
hostName = hName;
fromPort=fPort;
toPort=tPort;
dgSock = new DatagramSocket(fromPort);
ta.append("Ready To Send ...\n");
RunningThreadDG rt = new RunningThreadDG(dgSock,ta);
Thread thread = new Thread(rt);
thread.start();
}
catch(Exception e)
{
}
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource()==btn)
{
try
{
byte buff[] = new byte[500];
InetAddress remoteHost = InetAddress.getByName(hostName);
buff=tf.getText().getBytes();
dgSock.send(new DatagramPacket(buff,buff.length,remoteHost.getLocalHost(),toPort));
ta.append("Send : " + tf.getText() + "\n");
tf.setText("");
}
catch(Exception e)
{
}
}
else
{
System.exit(0);
}
}
}
class RunningThreadDG extends Frame implements Runnable
{
DatagramSocket dgSock;
TextArea ta;
String str;
RunningThreadDG(DatagramSocket dgs,TextArea t)
{
dgSock=dgs;
ta=t;
}
public void run()
{
byte[] buff = new byte[500];
while(true)
{
try
{
DatagramPacket dgPack = new DatagramPacket(buff,buff.length);
dgSock.receive(dgPack);
ta.append("Received : " + new String(dgPack.getData(),0,dgPack.getLength()) + "\n");
}
catch(Exception e)
{
}
}
}
}
Here's a problem:
dgSock.send(new DatagramPacket(buff,buff.length,remoteHost.getLocalHost(),toPort));
remoteHost.getLocalHost() returns an InetAddress for your local host. Try just passing remoteHost instead of remoteHost.getLocalHost():
dgSock.send(new DatagramPacket(buff,buff.length,remoteHost,toPort));
In addtion to echo's answer I would like to add that you should at least add e.printStackTrace(); to your catch blocks.
Also check whether both machines can resolve each others hostnames by calling nslookup hostname. Or just ping hostname from each machine.
Are there any examples of a server and a client that use sockets, but that have send and get methods? I'm doing this networked battleship program, almost finished, but can't get the server and clients to work. I have made a chat program that only sends strings, but this time I need to send objects. I'm already frustrated, so is there any source code that already has this.
Here's the code for the client... how would you modify it to allow to send objects? Also I need to be listening for incoming objects and process them right away.
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SimpleChat extends JFrame {
private Socket communicationSocket = null;
private PrintWriter outStream = null;
private BufferedReader inStream = null;
private Boolean communicationContinue = true;
private String disconnectString = "disconnect764*#$1";
private JMenuItem disconnectItem;
private JTextField displayLabel;
private final Color colorValues[] = { Color.black, Color.blue, Color.red, Color.green };
// set up GUI
public SimpleChat() {
super("Simple Chat");
// set up File menu and its menu items
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic('F');
// set up Activate Server menu item
JMenuItem serverItem = new JMenuItem("Activate Server");
serverItem.setMnemonic('S');
fileMenu.add(serverItem);
serverItem.addActionListener(new ActionListener() { // anonymous inner class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
setUpServer();
}
} // end anonymous inner class
); // end call to addActionListener
// set up Activate Client menu item
JMenuItem clientItem = new JMenuItem("Activate Client");
clientItem.setMnemonic('C');
fileMenu.add(clientItem);
clientItem.addActionListener(new ActionListener() { // anonymous inner class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
setUpClient();
}
} // end anonymous inner class
); // end call to addActionListener
// set up Activate Client menu item
disconnectItem = new JMenuItem("Disconnect Client/Server");
disconnectItem.setMnemonic('D');
disconnectItem.setEnabled(false);
fileMenu.add(disconnectItem);
disconnectItem.addActionListener(new ActionListener() { // anonymous inner
// class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
disconnectClientServer(true);
}
} // end anonymous inner class
); // end call to addActionListener
// set up About... menu item
JMenuItem aboutItem = new JMenuItem("About...");
aboutItem.setMnemonic('A');
fileMenu.add(aboutItem);
aboutItem.addActionListener(new ActionListener() { // anonymous inner class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(SimpleChat.this, "This is an example\nof using menus", "About",
JOptionPane.PLAIN_MESSAGE);
}
} // end anonymous inner class
); // end call to addActionListener
// set up Exit menu item
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.setMnemonic('x');
fileMenu.add(exitItem);
exitItem.addActionListener(new ActionListener() { // anonymous inner class
// terminate application when user clicks exitItem
public void actionPerformed(ActionEvent event) {
disconnectClientServer(true);
System.exit(0);
}
} // end anonymous inner class
); // end call to addActionListener
// create menu bar and attach it to MenuTest window
JMenuBar bar = new JMenuBar();
setJMenuBar(bar);
bar.add(fileMenu);
// set up label to display text
displayLabel = new JTextField("Sample Text", SwingConstants.CENTER);
displayLabel.setForeground(colorValues[0]);
displayLabel.setFont(new Font("Serif", Font.PLAIN, 72));
displayLabel.addActionListener(new ActionListener() { // anonymous inner
// class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
sendData();
}
} // end anonymous inner class
); // end call to addActionListener
getContentPane().setBackground(Color.CYAN);
getContentPane().add(displayLabel, BorderLayout.CENTER);
setSize(500, 200);
setVisible(true);
} // end constructor
public static void main(String args[]) {
final SimpleChat application = new SimpleChat();
application.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
application.disconnectClientServer(true);
System.exit(0);
}
});
// application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public void setCommunicationSocket(Socket sock) {
communicationSocket = sock;
communicationContinue = true;
disconnectItem.setEnabled(true);
}
public void setOutStream(PrintWriter out) {
outStream = out;
}
public void setInStream(BufferedReader in) {
inStream = in;
}
public void setUpServer() {
ServerThread st = new ServerThread(this);
st.start();
}
public void setUpClient() {
ClientThread st = new ClientThread(this);
st.start();
}
public void disconnectClientServer(Boolean sendMessage) {
if (communicationSocket == null)
return;
try {
// shut down socket read loop
communicationContinue = false;
disconnectItem.setEnabled(false);
// send notification to other end of socket
if (sendMessage == true)
outStream.println(disconnectString);
// sleep to let read loop shut down
Thread t = Thread.currentThread();
try {
t.sleep(500);
} catch (InterruptedException ie) {
return;
}
outStream.close();
inStream.close();
communicationSocket.close();
} catch (IOException e) {
System.err.println("Stream Read Failed.");
JOptionPane.showMessageDialog(SimpleChat.this, "Disconnection Failed", "SimpleChat", JOptionPane.PLAIN_MESSAGE);
return;
} finally {
communicationSocket = null;
}
}
public void sendData() {
if (communicationSocket != null) {
String data = displayLabel.getText();
outStream.println(data);
}
}
public void getData() {
String inputLine;
try {
while (communicationContinue == true) {
communicationSocket.setSoTimeout(100);
// System.out.println ("Waiting for Connection");
try {
while (((inputLine = inStream.readLine()) != null)) {
System.out.println("From socket: " + inputLine);
if (inputLine.equals(disconnectString)) {
disconnectClientServer(false);
return;
}
displayLabel.setText(inputLine);
}
} catch (SocketTimeoutException ste) {
// System.out.println ("Timeout Occurred");
}
} // end of while loop
System.out.println("communication is false");
} catch (IOException e) {
System.err.println("Stream Read Failed.");
JOptionPane.showMessageDialog(SimpleChat.this, "Input Stream read failed", "SimpleChat",
JOptionPane.PLAIN_MESSAGE);
return;
}
}
}
class ServerThread extends Thread {
private SimpleChat sc;
private JTextField display;
public ServerThread(SimpleChat scParam) {
sc = scParam;
}
public void run() {
ServerSocket connectionSocket = null;
try {
connectionSocket = new ServerSocket(10007);
} catch (IOException e) {
System.err.println("Could not listen on port: 10007.");
JOptionPane.showMessageDialog(sc, "Could not listen on port: 10007", "Server", JOptionPane.PLAIN_MESSAGE);
return;
}
JOptionPane.showMessageDialog(sc, "Server Socket is now activated", "Server", JOptionPane.PLAIN_MESSAGE);
Socket communicationSocket = null;
try {
communicationSocket = connectionSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
JOptionPane.showMessageDialog(sc, "Accept failed", "Server", JOptionPane.PLAIN_MESSAGE);
return;
}
JOptionPane.showMessageDialog(sc, "Comminucation is now activated", "Server", JOptionPane.PLAIN_MESSAGE);
try {
PrintWriter out = new PrintWriter(communicationSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(communicationSocket.getInputStream()));
sc.setCommunicationSocket(communicationSocket);
sc.setOutStream(out);
sc.setInStream(in);
connectionSocket.close();
sc.getData();
} catch (IOException e) {
System.err.println("Accept failed.");
JOptionPane.showMessageDialog(sc, "Creation of Input//Output Streams failed", "Server", JOptionPane.PLAIN_MESSAGE);
return;
}
}
}
class ClientThread extends Thread {
private SimpleChat sc;
public ClientThread(SimpleChat scParam) {
sc = scParam;
}
public void run() {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
String ipAddress = "127.0.0.1";
try {
echoSocket = new Socket(ipAddress, 10007);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + ipAddress);
JOptionPane.showMessageDialog(sc, "Don't know about host: " + ipAddress, "Client", JOptionPane.PLAIN_MESSAGE);
return;
} catch (IOException e) {
System.err.println("Couldn't get I/O for " + "the connection to: " + ipAddress);
JOptionPane.showMessageDialog(sc, "Couldn't get I/O for the connection to: " + ipAddress, "Client",
JOptionPane.PLAIN_MESSAGE);
return;
}
JOptionPane.showMessageDialog(sc, "Comminucation is now activated", "Client", JOptionPane.PLAIN_MESSAGE);
sc.setCommunicationSocket(echoSocket);
sc.setOutStream(out);
sc.setInStream(in);
sc.getData();
}
}
I suggest you read up on java serialization. There is an example here. Basically, there is built in serialization support. Your class needs to implement Serializable. Then you use ObjectOutputStream and ObjectInputStream to write object.
You would be well advised to use libraries that shield you from the error prone low level socket programming.
For C++ look to Boost (http://www.boost.com) or ACE (http://www.cs.wustl.edu/~schmidt/ACE.html)
For Java I only found a document that talks about the acceptor pattern http://www.hillside.net/plop/plop99/proceedings/Fernandez3/RACPattern.PDF
But I am sure there's an implementation out somewhere
Your on the right track. A chat program is a good place to start learning about sockets.
What you want is to use the ObjectOutputStream and ObjectInputStream classes. You simply have to wrap your input stream / output stream with these filters. ObjectOutputStream has a method writeObject(), and the ObjectInputStream has a corresponding readObject() method.
Most serialization examples show reading and writing objects to a file, but the same can be done using a socket stream. See http://www.acm.org/crossroads/xrds4-2/serial.html
I didn't bother to read through your piles and piles of code, but in general you can't directly send objects over the network. Network communication is just bits and bytes. If you want to send objects, you'll need to serialize them on the sending side, and de-serialize them on the receiving side. There are tons of methods of serializing, eg JSON, XML, or even Java's built-in serialization support (only recommended if both the client and server will always be Java).
You may find this code to be a decent starting point for making your own class. These are two classes I made to somewhat abstract the work needed for TCP and UDP socket protocols:
http://code.google.com/p/hivewars/source/browse/trunk/SocketData.java
http://code.google.com/p/hivewars/source/browse/trunk/UDPSocket.java
Quick dislaimer: These are kind of versions of a feature full class, I just added functionality as I needed it. However, it could help you start.