Using code examples from stockoverflow I made a class to receive data over TCP/IP.
Class code below. It is working OK and I do receive data from other PC.
recPositions Map is build correctly. After transmission is finished I can display all data I received using getRecPositions()
This thread is started in other class that build simple HMI screen.
Thread runs and display data received from other PC.
Problem is I would like to access same data in MainWindow class (HMI)
but it always show that nothing was received.
Class MainWindow below (not all of it since there is lots of useless pushbuttons and so on)
At the very bottom I have pushbutton that should display how many positions were recorded (elements in Map) but it always show 0.
Code snippet from push button update.
System.out.println(dataServer.getRecPositions().size())
So at some point I am doing something wrong.
Thread starts and runs and I can see incoming positions. At some point after I received "EOT" I display received positions stored in Map. But when I tried to display the size of Map in main window it always show 0.
/*
* Simple data server for receiving string data from IIWA robot
*/
public class SimpleDataServer implements Runnable {
Map<Integer, String> recPositions = new HashMap<>();
Server1Connection oneconnection;
ServerSocket echoServer = null;
Socket clientSocket = null;
int port;
boolean reset = false;
public SimpleDataServer( int port ) {
this.port = port;
}
public void stopServer() {
System.out.println( "Simple data server stopped" );
}
public void startServer() {
// Try to open a server socket on the given port
// Note that we can't choose a port less than 1024 if we are not
// privileged users (root)
try {
echoServer = new ServerSocket(port);
}
catch (IOException e) {
System.out.println(e);
}
System.out.println( "Waiting for connections. Only one connection is allowed." );
// Create a socket object from the ServerSocket to listen and accept connections.
// Use Server1Connection to process the connection.
while ( true ) {
try {
clientSocket = echoServer.accept();
oneconnection = new Server1Connection(clientSocket, this);
oneconnection.run();
if(isReset()) {
setReset(false);
System.out.println("Recording finished");
System.out.println("DEBUG:" + this.getRecPositions().size() + " positions recorded: " + this.getRecPositions());
}
}
catch (IOException e) {
System.out.println(e);
}
}
}
#Override
public void run() {
int port = this.port;
SimpleDataServer server = new SimpleDataServer( port );
server.startServer();
}
public Map<Integer, String> getRecPositions() {
return recPositions;
}
public void setRecPositions(Map<Integer, String> recPositions) {
this.recPositions = recPositions;
}
public boolean isReset() {
return reset;
}
public void setReset(boolean reset) {
this.reset = reset;
}
}
class Server1Connection {
BufferedReader is;
PrintStream os;
Socket clientSocket;
SimpleDataServer server;
public Server1Connection(Socket clientSocket, SimpleDataServer server) {
this.clientSocket = clientSocket;
this.server = server;
System.out.println( "Connection established with: " + clientSocket );
try {
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintStream(clientSocket.getOutputStream());
} catch (IOException e) {
System.out.println(e);
}
}
public Map<Integer, String> getPositions() {
return server.getRecPositions();
}
public void run() {
String line; //whole line recevied
String segment = null; //single segment from line using comma delimiter
List<String> stringsList;
try {
boolean serverStop = false;
//server runs here
while (true)
{
line = is.readLine();
System.out.println( "DEBUG Server Received: " + line );
//check is string is not empty
if (line.equals(null)) {
System.err.println("Empty String received");
break;
}
stringsList = new ArrayList<String>(Arrays.asList(line.split(";")));
if (!stringsList.isEmpty()) {
stringsList.set(0, stringsList.get(0).replaceAll("\\s+",""));
stringsList.set((stringsList.size()-1), stringsList.get(stringsList.size()-1).replaceAll("\\s+",""));
String lastSegment = stringsList.get((stringsList.size()-1));
if (lastSegment.equals("ETX") || lastSegment.equals("EOT")) {
switch (stringsList.get(0)) {
case "MSG":
stringsList.remove(0);
stringsList.remove(stringsList.size()-1);
System.out.println("Message: " + stringsList.toString());
break;
case "POS":
// for (String blah : stringsList) {
// System.out.println("DEBUG" + blah);
// }
iiwaPosfromString iiwaPos = new iiwaPosfromString(stringsList.get(1), stringsList.get(2));
System.out.println("DEBUG Position number: " + iiwaPos.posNum + " ; " + iiwaPos.toString());
if (iiwaPos.getPosNum() > 0) {
server.getRecPositions().put(iiwaPos.getPosNum(), iiwaPos.toString());
}
break;
case "EOT":
case "EXT":
//ignore handled later
break;
default:
System.err.println("Ausgebombt!");
break;
}
}
//ETX End Of Text - dump data to screen - close current connection
if(lastSegment.equals("ETX")) {
System.out.println("End of Text received");
break;
}
//EOT End Of Transmission - shuts down server
if(lastSegment.equals("EOT")) {
System.out.println("End of Transmission received");
serverStop = true;
server.setReset(true);
break;
}
System.err.println("No correct end string!");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
} else {
System.out.println("Empty String received");
break;
}
}
System.out.println( "Connection closed." );
is.close();
os.close();
clientSocket.close();
if ( serverStop ) server.stopServer();
} catch (IOException e) {
System.out.println(e);
}
}
public class iiwaPosfromString {
private double posX;
private double posY;
private double posZ;
private double posA;
private double posB;
private double posC;
private int posNum;
public iiwaPosfromString(String posNum, String posString) {
List <String>stringsList = new ArrayList<String>(Arrays.asList(posString.split(" ")));
for (int i = 0; i < stringsList.size(); i++) {
String newElement = stringsList.get(i);
newElement = newElement.replaceAll("[^\\d.]", "");
stringsList.set(i, newElement);
}
this.setPosNum(Integer.parseInt(posNum));
this.setPosX(Double.parseDouble(stringsList.get(1)));
this.setPosY(Double.parseDouble(stringsList.get(2)));
this.setPosZ(Double.parseDouble(stringsList.get(3)));
//this is stupid and don't do that
//from right to left, string to double, change radians to degrees, format to two decimals(string), string to double again
this.setPosA(Double.parseDouble(String.format("%.2f",(Math.toDegrees(Double.parseDouble(stringsList.get(4)))))));
this.setPosB(Double.parseDouble(String.format("%.2f",(Math.toDegrees(Double.parseDouble(stringsList.get(4)))))));
this.setPosC(Double.parseDouble(String.format("%.2f",(Math.toDegrees(Double.parseDouble(stringsList.get(4)))))));
}
public double getPosX() {
return posX;
}
public void setPosX(double posX) {
this.posX = posX;
}
public double getPosY() {
return posY;
}
public void setPosY(double posY) {
this.posY = posY;
}
public double getPosZ() {
return posZ;
}
public void setPosZ(double posZ) {
this.posZ = posZ;
}
public double getPosA() {
return posA;
}
public void setPosA(double posA) {
this.posA = posA;
}
public double getPosB() {
return posB;
}
public void setPosB(double posB) {
this.posB = posB;
}
public double getPosC() {
return posC;
}
public void setPosC(double posC) {
this.posC = posC;
}
#Override
public String toString() {
return "<" +
"X: " + getPosX() + ", " +
"Y: " + getPosY() + ", " +
"Z: " + getPosZ() + ", " +
"A: " + getPosA() + ", " +
"B: " + getPosB() + ", " +
"C: " + getPosC() +
">";
}
public int getPosNum() {
return posNum;
}
public void setPosNum(int posNum) {
this.posNum = posNum;
}
}
}
public class MainWindow {
private Thread dataServerThread;
private SimpleDataServer dataServer;
private XmlParserGlobalVarsRD globalVarPLC, globalVarKRC;
private JFrame frame;
private JTextField simpleWorkingDirStiffness;
private JTextField simpleWorkingDirAdditionalForce;
private JTextField simpleTravelDistance;
private JTextField simpleTravelVelocity;
private JTextField simpleTotalTime;
private JTextField simpleTheoreticalDepth;
private JTextField simpleZProgress;
private JComboBox oscillationMode;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Throwable e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWindow window = new MainWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainWindow() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
final JCheckBox emptyScanCycle = new JCheckBox("VRSI Scan Cycle Plain Fasteners");
//set data server thread and start it
dataServer = new SimpleDataServer(30008);
dataServerThread = new Thread(dataServer);
dataServerThread.setDaemon(true);
dataServerThread.start();
...
JButton pbUpdate = new JButton("UPDATE");
pbUpdate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.out.println(dataServer.getRecPositions().size())
}
});
pbUpdate.setBounds(210, 176, 90, 28);
frame.getContentPane().add(pbUpdate);
}
I believe the issue is in your SimpleDataServer.run method. You are creating a separate instance of SimpleDataServer from WITHIN your SimpleDataServer instance. Therefore, all of the communication is taking place in an object that your MainWindow has no direct reference to. I believe your SimpleDataServer.run method should look like this:
#Override
public void run() {
this.startServer();
}
Related
I'm writing a chat room server which takes message from a chat client and broadcasts out the message to all users. This is an exercise from a book called An Introduction to Network Programming with Java: Java 7 Compatible with which I'm self-teaching Java networking basics. I wrote a GUI frontend for the chat room and implemented the server backend, following examples from the code in the book. However, when I tested the code with chat clients, the server seemed unable to receive clients' data. I can't figure out why. The code for the chat room (here it was made in command line mode for test purpose) and the client is as followings. Thank you.
// code for the server backend, problem seems to be lie in here.
/**
* The multiecho server itself
*/
package channelEchoServer;
import java.net.*;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
public class MultiEchoServerNIO {
private static ServerSocketChannel serverSocketChannel;
private static final int PORT = 1234;
private static Selector selector;
private static Vector<SocketChannel> socketChannelVec;
private static Vector<ChatUser> allUsers;
public static final int CAPACITY = 20;
public static final int BUFFER_SIZE = 2048;
public static final String NEW_LINE = System.lineSeparator();
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocket = serverSocketChannel.socket();
InetSocketAddress netAddress = new InetSocketAddress(PORT);
serverSocket.bind(netAddress);
selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}
catch (IOException ioEx) {
ioEx.printStackTrace();
System.exit(1);
}
socketChannelVec = new Vector<>(CAPACITY);
allUsers = new Vector<>(CAPACITY);
System.out.println("Server is opened ...");
processConnections();
}
private static void processConnections () {
do {
try {
int numKeys = selector.select();
System.out.println(numKeys + " keys selected.");
if (numKeys > 0) {
Set eventKeys = selector.selectedKeys();
Iterator keyCycler = eventKeys.iterator();
while (keyCycler.hasNext()) {
SelectionKey key = (SelectionKey)keyCycler.next();
int keyOps = key.readyOps();
if ((keyOps & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
acceptConnection(key);
continue;
}
if ((keyOps & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
acceptData(key);
}
}
}
}
catch (IOException ioEx) {
ioEx.printStackTrace();
System.exit(1);
}
} while (true);
}
private static void acceptConnection (SelectionKey key) throws IOException {
SocketChannel socketChannel;
Socket socket;
socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socket = socketChannel.socket();
System.out.println("Connection on " + socket + ".");
socketChannel.register(selector, SelectionKey.OP_READ);
socketChannelVec.add(socketChannel);
selector.selectedKeys().remove(key);
}
private static void acceptData (SelectionKey key) throws IOException {
SocketChannel socketChannel;
Socket socket;
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
socketChannel = (SocketChannel) key.channel();
buffer.clear();
int numBytes = socketChannel.read(buffer);
socket = socketChannel.socket();
if (numBytes == -1) {
key.cancel();
closeSocket(socket);
}
else {
String chatName = null;
byte[] byteArray = buffer.array();
if (byteArray[0] == '#')
announceNewUser(socketChannel, buffer);
else {
for (ChatUser chatUser : allUsers)
if (chatUser.getUserSocketChannel().equals(socketChannel))
chatName = chatUser.getChatName();
broadcastMessage(chatName, buffer);
}
}
}
private static void closeSocket (Socket socket) {
try {
if (socket != null)
socket.close();
}
catch (IOException ioEx) {
System.out.println("Unable to close socket!");
}
}
public static void announceNewUser (SocketChannel userSocketChannel, ByteBuffer buffer) {
ChatUser chatUser;
byte[] byteArray = buffer.array();
int messageSize = buffer.position();
String chatName = new String(byteArray, 1, messageSize);
if (chatName.indexOf("\n") >= 0)
chatName = chatName.substring(0, chatName.indexOf("\n"));
chatUser = new ChatUser(userSocketChannel, chatName);
allUsers.add(chatUser);
if (!socketChannelVec.remove(userSocketChannel)) {
System.out.println("Can't find user!");
return;
} // we should save userSocketChannel in a chatUser instance before deleting it.
chatName = chatUser.getChatName();
System.out.println(chatName + " entered the chat room at " + new Date() + "." + NEW_LINE);
String welcomeMessage = "Welcome " + chatName + "!" + NEW_LINE;
byte[] bytes = welcomeMessage.getBytes();
buffer.clear();
for (int i = 0; i < welcomeMessage.length(); i++)
buffer.put(bytes[i]);
buffer.flip();
try {
chatUser.getUserSocketChannel().write(buffer);
}
catch (IOException ioEx) {
ioEx.printStackTrace();
}
}
public static void announceExit (String name) {
System.out.println(name + " left chat room at " + new Date() + "." + NEW_LINE);
for (ChatUser chatUser : allUsers) {
if (chatUser.getChatName().equals(name))
allUsers.remove(chatUser);
}
}
public static void broadcastMessage (String chatName, ByteBuffer buffer) {
String messagePrefix = chatName + ": ";
byte[] messagePrefixBytes = messagePrefix.getBytes();
final byte[] CR = NEW_LINE.getBytes();
try {
int messageSize = buffer.position();
byte[] messageBytes = buffer.array();
byte[] messageBytesCopy = new byte[messageSize];
String userMessage = new String(messageBytes, 0, messageSize);
if (userMessage.equals("Bye"))
announceExit(chatName);
for (int i = 0; i < messageSize; i++)
messageBytesCopy[i] = messageBytes[i];
buffer.clear();
buffer.put(messagePrefixBytes);
for (int i = 0; i < messageSize; i++)
buffer.put(messageBytesCopy[i]);
buffer.put(CR);
SocketChannel chatSocketChannel;
for (ChatUser chatUser : allUsers) {
chatSocketChannel = chatUser.getUserSocketChannel();
buffer.flip();
chatSocketChannel.write(buffer);
}
}
catch (IOException ioEx) {
ioEx.printStackTrace();
}
}
}
class ChatUser {
private SocketChannel userSocketChannel;
private String chatName;
public ChatUser (SocketChannel userSocketChannel, String chatName) {
this.userSocketChannel = userSocketChannel;
this.chatName = chatName;
}
public SocketChannel getUserSocketChannel () {
return userSocketChannel;
}
public String getChatName () {
return chatName;
}
}
// Code for a chat client for testing purpose
package multithreadEchoChatroomClientGUI;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;
public class MultithreadEchoChatroomClient1 {
private static Socket socket;
private static InetAddress host;
private static String address;
public static final int PORT = 1234;
public static void main(String[] args) {
address = JOptionPane.showInputDialog("Enter the host name or IP address:");
try {
host = InetAddress.getByName(address);
}
catch (UnknownHostException uhEx) {
JOptionPane.showMessageDialog(null, "Unknown Host!", "Error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
try {
socket = new Socket(host, PORT);
}
catch (IOException ioEx) {
JOptionPane.showMessageDialog(null, ioEx.toString(), "Error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
SwingUtilities.invokeLater(new Runnable () {
public void run () {
ClientFrame client = new ClientFrame(host, socket, address);
client.setTitle("Chat");
client.setSize(400, 500);
client.setVisible(true);
new Thread(client).start();
}
});
}
}
class ClientFrame extends JFrame implements Runnable {
private InetAddress host;
private String address;
private Socket socket;
private Scanner input;
private PrintWriter output;
private JMenuItem connect;
private JTextArea serverResponseArea;
private JTextArea messageArea;
private JTextField messageFiled;
private JButton sendButton;
private String serverResponse;
private String clientName;
public ClientFrame (InetAddress host, Socket socket, String address) {
this.host = host;
this.socket = socket;
this.address = address;
initFrame();
}
public void run () {
try {
input = new Scanner(socket.getInputStream());
output = new PrintWriter(socket.getOutputStream(), true);
}
catch (IOException ioEx) {
JOptionPane.showMessageDialog(this, "Cannot create input or output stream!", "Error", JOptionPane.ERROR_MESSAGE);
closeSocket();
System.exit(1);
}
do {
clientName = JOptionPane.showInputDialog("What nickname would you like to use in the chatroom?");
} while (clientName == null);
output.println("#" + clientName);
do {
serverResponse = input.nextLine();
serverResponseArea.append(serverResponse + "\n");
} while (socket.isClosed() != true);
}
private final void closeSocket () {
try {
socket.close();
}
catch (IOException ioEx) {
JOptionPane.showMessageDialog(this, "Cannot disconnect from chatroom!", "Error", JOptionPane.ERROR_MESSAGE);
}
}
private void initFrame () {
JMenuBar menuBar = createMenuBar();
setJMenuBar(menuBar);
JScrollPane responsePanel = createResponsePanel();
add(responsePanel, BorderLayout.NORTH);
JPanel messagePanel = createMessagePanel();
add(messagePanel, BorderLayout.CENTER);
//JPanel textPanel = createTextPanel();
//add(textPanel, BorderLayout.SOUTH);
addWindowListener(new WindowAdapter () {
#Override
public void windowClosing (WindowEvent we) {
if (!socket.isClosed())
closeSocket();
System.exit(0);
}
});
}
private JMenuBar createMenuBar () {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Operations");
connect = new JMenuItem("Connect");
connect.setEnabled(false);
connect.addActionListener(new ActionListener () {
#Override
public void actionPerformed (ActionEvent event) {
try {
host = InetAddress.getByName(address);
}
catch (UnknownHostException uhEx) {
JOptionPane.showMessageDialog(null, "Unknown Host!", "Error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
try {
socket = new Socket(host, MultithreadEchoChatroomClient1.PORT);
}
catch (IOException ioEx) {
JOptionPane.showMessageDialog(null, ioEx.toString(), "Error", JOptionPane.ERROR_MESSAGE);
}
try {
input = new Scanner(socket.getInputStream());
output = new PrintWriter(socket.getOutputStream(), true);
}
catch (IOException ioEx) {
JOptionPane.showMessageDialog(ClientFrame.this, "Cannot create input or output stream!", "Error", JOptionPane.ERROR_MESSAGE);
closeSocket();
System.exit(1);
}
output.println("#" + clientName);
serverResponse = input.nextLine();
serverResponseArea.append(serverResponse + "\n");
}
});
JMenuItem quit = new JMenuItem("Quit");
quit.addActionListener(new ActionListener() {
#Override
public void actionPerformed (ActionEvent event) {
if (!socket.isClosed())
closeSocket();
System.exit(0);
}
});
menu.add(connect);
menu.add(quit);
menuBar.add(menu);
return menuBar;
}
private JScrollPane createResponsePanel () {
serverResponseArea = new JTextArea(20, 35);
serverResponseArea.setEditable(false);
serverResponseArea.setLineWrap(true);
serverResponseArea.setWrapStyleWord(true);
serverResponseArea.setMargin(new Insets(5, 5, 5, 5));
JScrollPane scrlPane = new JScrollPane(serverResponseArea);
scrlPane.setBorder(BorderFactory.createEmptyBorder(20, 10, 10, 20));
scrlPane.setBackground(Color.yellow);
return scrlPane;
}
private JPanel createMessagePanel () {
JPanel msgPanel = new JPanel();
msgPanel.setBorder(BorderFactory.createEmptyBorder(20,10, 10, 20));
msgPanel.setBackground(Color.blue);
msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.LINE_AXIS));
JScrollPane srlPanel = createMessageTextPanel();
msgPanel.add(srlPanel);
JButton sdButton = createSendButton();
msgPanel.add(sdButton);
return msgPanel;
}
private JScrollPane createMessageTextPanel () {
messageArea = new JTextArea(10, 35);
//messageArea.setEditable(false);
messageArea.setLineWrap(true);
messageArea.setWrapStyleWord(true);
messageArea.setMargin(new Insets(5, 5, 5, 5));
JScrollPane mtPanel = new JScrollPane(messageArea);
return mtPanel;
}
private JButton createSendButton () {
JButton button = new JButton("Send");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed (ActionEvent event) {
String message;
message = messageArea.getText();
System.out.println(message);
output.println(message);
if (message.equals("Bye")) {
closeSocket();
connect.setEnabled(true);
}
messageArea.setText("");
//serverResponse = input.nextLine();
//serverResponseArea.append(serverResponse + "\n");
}
});
return button;
}
}
Thank you again for taking so much trouble reading much code and giving suggestions!
The problem is solved according to #user207421. I should have put a remove() operation in the else {} block in the method acceptData(SelectedKey key) so that the old key associated with the socketChannel is removed from the selected key set for new incoming keys to be able to be detected.
I don't know whether my understanding of user207421's solution was right or not, but it did solve the problem for now. If anybody has any other ideas, please share your views.
Thank you again, user207421. And thank all visitors to this post for your attention.
Hey all new to Java some I'm sure this is something simple but just can not get it correctly in order for it to work.
The original java code for this runnable class:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChatServer {
private static Set < String > names = new HashSet < > ();
private static Set < PrintWriter > writers = new HashSet < > ();
public static int thePort = 8877;
private static boolean isPortInUse(String host, int port) throws SocketException {
boolean result = false;
try {
(new Socket(host, port)).close();
result = true;
} catch (IOException e) {
// Could not connect.
}
return result;
}
#SuppressWarnings("unused")
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running...");
ExecutorService pool = Executors.newFixedThreadPool(500);
boolean hasPort = isPortInUse("localhost", thePort);
try (ServerSocket listener = new ServerSocket(thePort)) {
while (true) {
pool.execute(new Handler(listener.accept()));
}
}
}
private static class Handler implements Runnable {
private String name;
private Socket socket;
private Scanner in ;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
in = new Scanner(socket.getInputStream());
out = new PrintWriter(socket.getOutputStream(), true);
while (true) {
out.println("SUBMITNAME");
name = in .nextLine();
if (name == null) {
return;
}
synchronized(names) {
if (!name.isEmpty() && !names.contains(name)) {
names.add(name);
break;
}
}
}
out.println("NAMEACCEPTED " + name);
for (PrintWriter writer: writers) {
writer.println("MESSAGE " + name + " has joined");
}
writers.add(out);
while (true) {
String input = in .nextLine();
if (input.toLowerCase().startsWith("/quit")) {
return;
}
for (PrintWriter writer: writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (Exception e) {
System.out.println(e);
} finally {
if (out != null) {
writers.remove(out);
}
if (name != null) {
System.out.println(name + " has left");
names.remove(name);
for (PrintWriter writer: writers) {
writer.println("MESSAGE " + name + " has left");
}
}
try {
socket.close();
} catch (IOException e) {}
}
}
}
}
The thread code that I created is this:
static Thread serverThread = new Thread(new Runnable() {
private String name;
private Socket socket;
private Scanner in ;
private PrintWriter out;
#Override
public void run() {
try {
Set < String > names = new HashSet < > ();
Set < PrintWriter > writers = new HashSet < > ();
int thePort = 8877;
System.out.println("The chat server is running...");
ExecutorService pool = Executors.newFixedThreadPool(500);
boolean hasPort = isPortInUse("localhost", thePort);
try (ServerSocket listener = new ServerSocket(thePort)) {
while (true) {
pool.execute(new Handler(listener.accept()));
}
}
try {
in = new Scanner(socket.getInputStream());
out = new PrintWriter(socket.getOutputStream(), true);
while (true) {
out.println("SUBMITNAME");
name = in .nextLine();
if (name == null) {
return;
}
synchronized(names) {
if (!name.isEmpty() && !names.contains(name)) {
names.add(name);
break;
}
}
}
out.println("NAMEACCEPTED " + name);
for (PrintWriter writer: writers) {
writer.println("MESSAGE " + name + " has joined");
}
writers.add(out);
while (true) {
String input = in .nextLine();
if (input.toLowerCase().startsWith("/quit")) {
return;
}
for (PrintWriter writer: writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (Exception e) {
System.out.println(e);
} finally {
if (out != null) {
writers.remove(out);
}
if (name != null) {
System.out.println(name + " has left");
names.remove(name);
for (PrintWriter writer: writers) {
writer.println("MESSAGE " + name + " has left");
}
}
try {
socket.close();
} catch (IOException e) {}
}
} catch (Exception e) {
System.out.println(e);
}
}
public void Handler(Socket socket) {
this.socket = socket;
}
private boolean isPortInUse(String host, int port) throws SocketException {
boolean result = false;
try {
(new Socket(host, port)).close();
result = true;
} catch (IOException e) {
// Could not connect.
}
return result;
}
});
The only 2 errors I have out of all of that code above is:
Handler cannot be resolved to a type
on
pool.execute(new Handler(listener.accept()));
and
Return type for the method is missing
on
public Handler(Socket socket) {
So what do I need to change in order to replace Handler so that it will work with the thread code I created?
UPDATE #1
my main class where i call both server and client:
#SuppressWarnings({ "resource", "unused" })
private static void placeChatOnScreen() {
textField = new JTextField();
textField.setFont(new Font("Segoe UI", Font.PLAIN, 13));
textField.setDragEnabled(true);
textField.setBorder(new MatteBorder(1, 1, 1, 1, (Color) new Color(0, 0, 0)));
textField.setBounds(338, 838, 954, 22);
frame.getContentPane().add(textField);
messageArea = new JTextArea();
messageArea.setEditable(false);
messageArea.setFont(new Font("Segoe UI", Font.PLAIN, 13));
messageArea.setBorder(new MatteBorder(1, 1, 1, 1, (Color) new Color(0, 0, 0)));
messageArea.setDragEnabled(true);
messageArea.setName("chatArea");
messageArea.setWrapStyleWord(true);
messageArea.setBounds(338, 648, 954, 181);
frame.getContentPane().add(messageArea);
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
out.println(textField.getText());
textField.setText("");
}
});
// start server
final Thread serverThread = new Thread(new Handler());
serverThread.start();
// wait a bit
Thread.sleep(1000);
// start client
clientThread.start();
}
And this is the server class (as you said to put it in):
public class ChatServer {
private static Set<String> names = new HashSet<>();
private static Set<PrintWriter> writers = new HashSet<>();
public static int thePort = 8877;
private static boolean isPortInUse(String host, int port) throws SocketException {
boolean result = false;
try {
(new Socket(host, port)).close();
result = true;
}
catch(IOException e) {
// Could not connect.
}
return result;
}
#SuppressWarnings("unused")
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running...");
ExecutorService pool = Executors.newFixedThreadPool(500);
boolean hasPort = isPortInUse("localhost", thePort);
try (ServerSocket listener = new ServerSocket(thePort)) {
while (true) {
pool.execute(new Handler(listener.accept()));
}
}
}
public static class Handler implements Runnable {
private String name;
private Socket socket;
private Scanner in;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
in = new Scanner(socket.getInputStream());
out = new PrintWriter(socket.getOutputStream(), true);
while (true) {
out.println("SUBMITNAME");
name = in.nextLine();
if (name == null) {
return;
}
synchronized (names) {
if (!name.isEmpty() && !names.contains(name)) {
names.add(name);
break;
}
}
}
out.println("NAMEACCEPTED " + name);
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + " has joined");
}
writers.add(out);
while (true) {
String input = in.nextLine();
if (input.toLowerCase().startsWith("/quit")) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (Exception e) {
System.out.println(e);
} finally {
if (out != null) {
writers.remove(out);
}
if (name != null) {
System.out.println(name + " has left");
names.remove(name);
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + " has left");
}
}
try { socket.close(); } catch (IOException e) {}
}
}
}
}
update #2
You declared a private class, which won't be accessible from other classes
private static class Handler implements Runnable { ... }
So, simply mark it as public or package-private (no modifier), if they share the same package
public static class Handler implements Runnable { ... }
Then, do
final Thread serverThread = new Thread(new Handler());
serverThread.start();
I'm learning about sockets and how server/client communicates.
So far, I have my protocols figured out and managed to simulate a synthetic TCP three-way-handshake:
Client successfully connects to server and sends SYN.
Server receives SYN and replies SYNACK to client.
Client receives SYNACK, and replies ACK to server.
Thats it, all this is linearly executed in the Run() method under a while(true) loop of my Runnable client service in a new Thread. I don't know how a Button in the GUI class can tell my Client Service to send a specific packet when, say, a specific button in the UI is pressed while the service runs in a different thread.
I have an idea but correct me on this: somehow add ActionListeners for all the buttons in my GUI inside the Service class instead of the GUI..
Thanks.
PS. I'm using DataInputStream and DataOutputStream to read/write data from/to socket stream.
ClientService.java:
public class ClientService implements Runnable, GameProtocol {
private Socket socket;
private int clientNumber;
private GameClient client;
private JTextArea clientConsole;
private DataInputStream fromServer;
private DataOutputStream toServer;
public ClientService(Socket aSocket, GameClient aClient, JTextArea textArea) {
this.socket = aSocket;
this.client = aClient;
this.clientConsole = textArea;
}
private void buildStreams() throws Exception {
this.fromServer = new DataInputStream(this.socket.getInputStream());
this.toServer = new DataOutputStream(this.socket.getOutputStream());
}
public void sendPacket(int data) {
try {
this.toServer.writeInt(data);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
public void flushPacket() {
try {
this.toServer.flush();
} catch (Exception e) {
e.printStackTrace();
}
return;
}
public void run() {
try {
try {
buildStreams();
toServer.writeInt(PLAYER_SYN); // start synthetic three way handshake
toServer.flush();
if(fromServer.readInt() == SERVER_SYNACK) {
this.clientNumber = fromServer.readInt();
clientConsole.append("Client number from Server: " + clientNumber + "\n");
toServer.writeInt(PLAYER_ACK);
toServer.writeInt(this.clientNumber);
toServer.flush();
}
else {
clientConsole.append("Client -> Server Sync failed. Can't proceed.\n");
toServer.writeInt(PLAYER_QUIT);
toServer.flush();
socket.close();
System.exit(-1);
}
executeCommand();
} finally {
socket.close();
}
} catch (Exception e) {
System.out.println("Client Service: " + e.getMessage());
}
}
private void executeCommand() throws Exception {
boolean quit = false;
while(!quit) {
int command = -14324;
if(fromServer.available() > 0) {
command = fromServer.readInt();
}
switch (command) {
case WINNER:
clientConsole.append("You Win.\n");
break;
case LOSER:
clientConsole.append("You Lost.\n");
break;
case ENABLE_TURN:
client.enableTurn();
break;
case DISABLE_TURN:
client.disableTurn();
break;
}
}
}
}
GameClient.java:
public class GameClient extends JFrame implements GameProtocol {
/**
* TextArea size.
*/
private final int
TEXTAREA_ROWS = 5,
TEXTAREA_COLS = 40;
/**
* Client window size, unadjustable.
*/
private final int
FRAME_W = 535,
FRAME_H = 600;
// for Assignment 10
private Socket socket;
private DataOutputStream toServer;
private DataInputStream fromServer;
/**
* ArrayList of type Cards, by default, holds 20 cards.
*/
private ArrayList<Card> cards;
/**
* Console for debugging.
*/
private JTextArea gameConsole;
/**
* Button to terminate game
*/
private JButton quitButton;
/**
* Main Frame panels, cardsPanel and consolePanel are sub-panels of mainPanel.
*/
private JPanel mainPanel, cardsPanel, consolePanel;
/**
* Builds packets to be sent to the server
*/
private Packet packet;
/**
* players points, accumulated.
*/
private int points = 0;
/**
* card choice 1
*/
private int choice1 = -1;
/**
* card choice 2
*/
private int choice2 = -1;
/**
* for building packet arguments
*/
private static int packetBuilderCount = 0;
/**
* Counter for outbound and inbound packets
*/
private static int packetNumber = 1;
/**
* for timing out cards when recieving no match
*/
private Timer timer;
/**
* true when user is allowed to pick cards.
* false when another user is true
*/
private boolean isTurn = true;
// service
private ClientService service;
/**
* default contrustor. Builds JFrame and all components.
*/
public static void main(String[] args) {
new GameClient();
}
public GameClient() {
packet = new Packet();
buildButton();
buildCards();
addEventToCards(); // adds actionlistener to each card.
buildPanel();
buildTimer();
buildFrame();
buildConnection(); // for assignment 10
}
private void buildConnection() {
try {
this.socket = new Socket(HOST, PORT);
// this.toServer = new DataOutputStream(socket.getOutputStream());
// this.fromServer = new DataInputStream(socket.getInputStream());
gameConsole.append("Socket Connected\n");
service = new ClientService(socket, this, this.gameConsole);
new Thread(service).start();
} catch (SecurityException ex) {
System.out.println("Check your firewall or antivirus. Unable to establish connection to server.");
} catch (UnknownHostException ex) {
System.out.println("Host can't be found. Unable to establish connection to server.");
} catch (ConnectException ex) {
System.out.println("Connection refused. What now?");
ex.printStackTrace();
// ex.printStackTrace();
} catch (IOException ex) {
System.out.println("fuck......");
}
}
/**
* initializes the timer.
*/
private void buildTimer() {
int delay = 3000; // wait for 3000ms
timer = new Timer(delay, new AbstractAction() {
/**
* event handler for timer. Flips the cards back to face down position.
*/
#Override
public void actionPerformed(ActionEvent ae) {
flipCard(choice1, 10);
flipCard(choice2, 10);
}
});
}
/**
* Initializes JFrame
*/
private void buildFrame() {
this.setSize(FRAME_W, FRAME_H);
setResizable(false);
this.add(mainPanel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
/**
* Initializes and compiles panels together. Adds Cards to panels
*/
private void buildPanel() {
gameConsole = new JTextArea(TEXTAREA_ROWS, TEXTAREA_COLS);
JScrollPane scrollConsole = new JScrollPane(gameConsole);
scrollConsole.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_NEVER);
gameConsole.setEditable(false);
mainPanel = new JPanel();
mainPanel.setPreferredSize(new Dimension(535, 475));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
cardsPanel = new JPanel(new GridLayout(4, 5, 20, 20));
for(int i = 0; i < 20; i++) {
cardsPanel.add(this.cards.get(i));
}
consolePanel = new JPanel();
consolePanel.add(scrollConsole);
consolePanel.add(quitButton);
mainPanel.add(cardsPanel);
mainPanel.add(consolePanel);
}
/**
* builds quit button, adds action listener to handle click
*/
private void buildButton() {
quitButton = new JButton("Quit");
quitButton.addActionListener(e -> {
buildQuitPacket();
});
}
/**
* builds 20 Card object.
*/
private void buildCards() {
cards = new ArrayList<Card>();
Card temp;
for(int i = 0; i < 20; i++) {
temp = new Card();
cards.add(temp);
}
}
/**
* adds actionlistener to all 20 card objects.
*/
private void addEventToCards() {
for(int i = 0; i < 20; i++) {
final int INDEX = i;
cards.get(i).addActionListener(e -> buildButtonPacket(this.cards.get(INDEX).getId()));
}
}
/**
* Builds and sends a Packet when a card is chosen
* #param value The card ID which was chosen.
*/
private void buildButtonPacket(int value) {
if(!isTurn) {
this.gameConsole.append("Its not you're turn.\n");
return;
}
if(packetBuilderCount == 0) {
packet.writeCommandToPacket(PICKED_CARDS);
packet.writeValueToPacket(value);
packetBuilderCount++;
choice1 = value;
}
else if(packetBuilderCount == 1) {
packet.writeValueToPacket(value);
packetBuilderCount = 0;
writeToConsoleOutBound(packet.toString());
choice2 = value;
// try{
// out.print(this.packet.getPacket());
// out.flush();
// } catch (Exception e) {
// gameConsole.append("could not send packet.\n");
// }
packet.clearPacket();
}
}
/**
* For handling commands from recieved Packet
* #param recieved the Packet object recieved. Gets and handles command and possible arguments that follows.
* See GameProtocol class for packet command definitions.
*/
public void handlePacket(Packet recieved) {
int cmd = recieved.getCommand();
writeToConsoleInBound(recieved.toString());
int arg1 = -99;
int arg2 = -99;
switch (cmd) {
case SERVER_SYNACK:
arg1 = recieved.getFirstArg();
if(arg1 == 1) {
this.isTurn = true;
}
else if (arg1 == 0) {
this.isTurn = false;
}
else {
writeToConsoleError("Server sync failed. Terminating..");
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
writeToConsoleError(ex.getMessage());
} finally {
System.exit(-1);
}
}
break;
case CARDMATCH:
arg1 = recieved.getFirstArg();
arg2 = recieved.getSecondArg();
if(arg1 > 9) {
arg1 = 9;
}
if(arg2 > 9) {
arg2 = 9;
}
flipCard(choice1, arg1);
flipCard(choice2, arg2);
break;
case CARDNOMATCH:
// System.out.println("CLIENT: im going to sleep");
arg1 = recieved.getFirstArg();
arg2 = recieved.getSecondArg();
if(arg1 > 9) {
arg1 = 9;
}
if(arg2 > 9) {
arg2 = 9;
}
flipCard(choice1, arg1);
flipCard(choice2, arg2);
this.cardsPanel.revalidate();
this.cardsPanel.repaint();
this.consolePanel.revalidate();
this.consolePanel.repaint();
timer.setRepeats(false); //the timer should only go off once
timer.start();
break;
case SHOW_CARD:
arg1 = recieved.getFirstArg();
arg2 = recieved.getSecondArg();
if(arg1 < 0 || arg1 > 19) {
writeToConsoleError(" BAD PACKET ARGUMENT 1, \nCard index out of bounds");
}
else if(arg2 < 0 || arg2 > 10) {
writeToConsoleError(" BAD PACKET ARGUMENT 2, \nImage index out of bounds");
}
else {
flipCard(arg1, arg2);
}
break;
case ENABLE_TURN:
this.isTurn = true;
break;
case DISABLE_TURN:
this.isTurn = false;
break;
case WINNER:
this.gameConsole.append("You win!\n");
break;
case LOSER:
this.gameConsole.append("You lost :( \n");
break;
case ADD_POINTS:
arg1 = recieved.getFirstArg();
this.points += arg1;
this.gameConsole.append("** Gained " + Integer.toString(arg1) + ", you now have " + Integer.toString(this.points) + " points.\n");
break;
case OTHER_QUIT:
this.gameConsole.append("Other player forfeited. You win!\n");
break;
}
}
/**
* Builds a packet containing QUIT when quit button is pressed
* Only available when isTurn == true.
*/
private void buildQuitPacket() {
if(this.isTurn == false) {
this.gameConsole.append("You can only quit when it is your turn.");
return;
}
service.sendPacket(PLAYER_QUIT);
service.flushPacket();
// this.service.sendPacket(PLAYER_QUIT);
// this.service.flushPacket();
System.exit(0);
}
/**
* Writes the outgoing packet to the game console.
* #param msg the actual packet message.
*/
public void writeToConsoleOutBound(String msg) {
this.gameConsole.append(Integer.toString(packetNumber++) + ": SENDING: " + msg + "\n");
}
/**
* Writes the incoming packet to the game console.
* #param msg the actual packet message.
*/
public void writeToConsoleInBound(String msg) {
this.gameConsole.append(Integer.toString(packetNumber++) + ": RECEIVING: " + msg + "\n");
}
/**
* Writes an error to the game console.
* #param msg the error message.
*/
public void writeToConsoleError(String msg) {
this.gameConsole.append("Error handling packet number " + Integer.toString(packetNumber) + "." + msg + "\n");
}
/**
* Flips a Card object and show an image
* #param whichCard the card ID which will be flipped.
* #param imgID the image which will be shown on the flipped card.
*/
public void flipCard(int whichCard, int imgID) {
this.cards.get(whichCard).flipCard(imgID);
}
/**
* Accumulates points.
* #param amt the amount to be added.
*/
public void gainPoints(int amt) {
this.points += amt;
}
public void enableTurn() {
this.isTurn = true;
}
public void disableTurn() {
this.isTurn = false;
}
}
Your connection to a socket works because it is in a constructor, no calls to modify a rendered element have been made (say update a button's text). Your client service needs a loop waiting for requests made by the UI, otherwise you would need to create a thread with every request made by the UI. It will become a bottleneck, specially in a game when one user action can trigger several UI updates. Look at the code posted you should follow more or less that pattern
package so;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
class ClientService implements Runnable{
JLabel label;
ConcurrentLinkedQueue<Long> work;
#Override
public void run() {
Long i = null;
try{
while(true){
if ((i = work.poll()) != null){
final long ii = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
label.setText(ii + "");
}
});
}
Thread.sleep(10);
}
}
catch(Exception x){
}
}
}
class GameClient extends JFrame{
Thread worker;
ConcurrentLinkedQueue<Long> work;
private JLabel label;
private JButton button;
GameClient(){
setLayout(new GridLayout(2, 1));
label = new JLabel("Label");
button = new JButton("Button");
button.addMouseListener(new MouseListener(){
#Override
public void mouseClicked(MouseEvent e) {
work.add(System.currentTimeMillis());
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
});
this.add(label);
this.add(button);
work = new ConcurrentLinkedQueue<Long>();
ClientService cs = new ClientService();
cs.label = this.label;
cs.work = this.work;
this.worker = new Thread(cs);
this.worker.start();
}
}
class SOCLass {
public static void main(String[] args){
SOCLass m = new SOCLass();
GameClient frame = new GameClient();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
frame.worker.interrupt();
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
}
I'm trying to make a chat function with Java. The problem is that I have two classes. One for Client and one for ClientGUI. Where the Client one has the logic parts and the ClientGUI the design. The problem is getting is in row 46 where new ListenFromServer().start(); is getting a error
No enclosing instance of type Controller is accessible. Must
qualify the allocation with an enclosing instance of type
COntroller(e.g. x.new A() where x is an instance of Controller).
So what I did was that I changedpublic class ListenFromServer extends Thread to a static. Which means public static class ListenFromServer extends Thread and now the problem that I'm getting
Error connecting to the server: java.net.ConnectException: connect: Address is invalid on local machine, or port is not valid on remote machine
Controller (Client logic)
package Server;
import java.io.*;
import java.net.*;
import java.util.*;
public class Controller {
private static ObjectInputStream input;
private static ObjectOutputStream output;
private static Socket socket;
private static ClientGUI clientgui;
private static String username;
private static String server;
private static int port;
public static boolean startClient(){
try{
socket = new Socket(server, port);
}catch (Exception ex){
System.out.print("Error connecting to the server: " + ex);
return false;
}
String message = "Connection is accepted; " + socket.getInetAddress() +" - "+ socket.getPort();
System.out.println(message);
try {
input=new ObjectInputStream(socket.getInputStream());
output =new ObjectOutputStream(socket.getOutputStream());
}
catch (IOException io) {
System.out.print("Exception creating new Input/Output Stream: "+ io);
return false;
}
**********new ListenFromServer().start();********* //The problem is here
try {
output.writeObject(username);
}
catch(IOException io) {
System.out.print("Exception doing login: " + io);
disconnect();
return false;
}
return true;
}
private void display(String message) {
if(clientgui == null)
System.out.println(message);
else
clientgui.append(message +"\n");
}
public static void sendMessage(Message message) {
try {
output.writeObject(message);
}
catch(IOException exd) {
System.out.print("Eceptionwritingtoserver: " + exd);
}
}
private static void disconnect() {
try {
if(input != null)
input.close();
}catch (Exception ex){}
try{
if(output != null)
output.close();
}catch(Exception ex){}
try{
if(socket != null)
socket.close();
}catch(Exception ex){};
if (clientgui != null)
clientgui.connectionFailed();
}
public class ListenFromServer extends Thread{
public void run() {
while(true){
try{
String message = (String) input.readObject();
if(clientgui == null){
System.out.println(message);
System.out.print(":");
}
else {
clientgui.append(message);
}
}
catch(IOException io){
System.out.print("Server has closed the connection");
if(clientgui != null)
clientgui.connectionFailed();
break;
}
catch(ClassNotFoundException classex){
}
}
}
}
}
ClientGUI
package Server;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/*
* The Client with its GUI
*/
public class ClientGUI extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JLabel lblusername;
private JTextField textfieldusername, textfieldserver, textfieldportnumber;
private JButton btnlogin, btnlogout, btnonline;
private JTextArea textareamessage;
private boolean connected;
private Client client;
private int defaultPort;
private String defaultHost;
ClientGUI(String host, int port) {
super("Chat Client");
defaultPort = port;
defaultHost = host;
JPanel northPanel = new JPanel(new GridLayout(2,2));
JPanel serverAndPort = new JPanel(new GridLayout(1,2, 2, 2));
JLabel lblserveraddress = new JLabel("Server Address: ");
JLabel lblchat = new JLabel(" #BallIsLife");
JLabel lblportnumber = new JLabel("Port Number: ");
textfieldserver = new JTextField(host);
textfieldserver.setHorizontalAlignment(SwingConstants.LEFT);
textfieldserver.setFont(new Font("Tahoma", Font.PLAIN, 20));
textfieldportnumber = new JTextField("" + port);
textfieldportnumber.setFont(new Font("Tahoma", Font.PLAIN, 20));
textfieldportnumber.setHorizontalAlignment(SwingConstants.LEFT);
lblserveraddress.setFont(new Font("Tahoma", Font.PLAIN, 19));
serverAndPort.add(lblserveraddress);
serverAndPort.add(textfieldserver);
serverAndPort.add(lblchat);
serverAndPort.add(lblportnumber);
serverAndPort.add(textfieldportnumber);
lblchat.setForeground(Color.RED);
lblportnumber.setFont(new Font("Tahoma", Font.PLAIN, 19));
northPanel.add(serverAndPort);
getContentPane().add(northPanel, BorderLayout.NORTH);
JPanel panelbtn = new JPanel();
northPanel.add(panelbtn);
btnlogin = new JButton("Login");
panelbtn.add(btnlogin);
btnlogin.setFont(new Font("Tahoma", Font.PLAIN, 17));
btnlogin.addActionListener(this);
btnonline = new JButton("Online");
panelbtn.add(btnonline);
btnonline.setFont(new Font("Tahoma", Font.PLAIN, 17));
btnonline.addActionListener(this);
btnonline.setEnabled(false);
btnlogout = new JButton("Logout");
panelbtn.add(btnlogout);
btnlogout.setFont(new Font("Tahoma", Font.PLAIN, 17));
btnlogout.addActionListener(this);
btnlogout.setEnabled(false);
JButton btnPicture = new JButton("Picture");
btnPicture.setFont(new Font("Tahoma", Font.PLAIN, 17));
btnPicture.setEnabled(false);
panelbtn.add(btnPicture);
textareamessage = new JTextArea("Welcome to the #BallIsLife Chat room.\n");
textareamessage.setFont(new Font("Monospaced", Font.PLAIN, 15));
textareamessage.setLineWrap(true);
textareamessage.setEditable(false);
JPanel centerPanel = new JPanel(new GridLayout(1,1));
JScrollPane scrollPane = new JScrollPane(textareamessage);
centerPanel.add(scrollPane);
getContentPane().add(centerPanel, BorderLayout.CENTER);
JPanel southPanel = new JPanel();
getContentPane().add(southPanel, BorderLayout.SOUTH);
lblusername = new JLabel("Enter your username", SwingConstants.CENTER);
lblusername.setFont(new Font("Tahoma", Font.PLAIN, 15));
southPanel.add(lblusername);
textfieldusername = new JTextField("Write your username here.");
textfieldusername.setFont(new Font("Tahoma", Font.PLAIN, 14));
textfieldusername.setColumns(50);
southPanel.add(textfieldusername);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(823, 665);
setVisible(true);
}
//Logiken
void append(String str) {
textareamessage.append(str);
textareamessage.setCaretPosition(textareamessage.getText().length() - 1);
}
void connectionFailed() {
btnlogin.setEnabled(true);
btnlogout.setEnabled(false);
btnonline.setEnabled(false);
lblusername.setText("Enter your username");
textfieldusername.setText("Write your username here");
textfieldportnumber.setText("" + defaultPort);
textfieldserver.setText(defaultHost);
textfieldserver.setEditable(false);
textfieldportnumber.setEditable(false);
textfieldusername.removeActionListener(this);
connected = false;
}
//
public void actionPerformed(ActionEvent e) {
Object button = e.getSource();
if(button == btnlogout) {
Controller.sendMessage(new Message("", Message.LOGOUT)); //Ändra till Chatmessage klass
btnlogin.setText("Login");
return;
}
if(button == btnonline) {
Controller.sendMessage(new Message("", Message.ONLINE)); //Ändra till Chatmessage klass
return;
}
if(connected) {
Controller.sendMessage(new Message(textfieldusername.getText(), Message.MESSAGE)); //Ändra till Chatmessage klass
textfieldusername.setText("");
return;
}
if(button == btnlogin) {
String username = textfieldusername.getText();
if(username.length() == 0)
return;
String server = textfieldserver.getText();
if(server.length() == 0)
return;
String portNumber = textfieldportnumber.getText();
if(portNumber.length() == 0)
return;
int port = 0;
try {
port = Integer.parseInt(portNumber);
}
catch(Exception en) {
return;
}
client = new Client(server, username, port, this);
if(!Controller.startClient())
return;
}
connected = true;
textfieldusername.setText("");
btnlogin.setText("Send message");
btnlogin.setEnabled(true);
btnlogout.setEnabled(true);
btnonline.setEnabled(true);
textfieldserver.setEditable(false);
textfieldportnumber.setEditable(false);
textfieldusername.addActionListener(this);
}
// to start the whole thing the server
public static void main(String[] args) {
new ClientGUI("localhost", 1500);
}
}
Server
package Server;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
/*
* The server that can be run both as a console application or a GUI
*/
public class Server {
// a unique ID for each connection
private static int uniqueId;
// an ArrayList to keep the list of the Client
private ArrayList<ClientThread> al;
// if I am in a GUI
private ServerGUI sg;
// to display time
private SimpleDateFormat sdf;
// the port number to listen for connection
private int port;
// the boolean that will be turned of to stop the server
private boolean keepGoing;
/*
* server constructor that receive the port to listen to for connection as parameter
* in console
*/
public Server(int port) {
this(port, null);
}
public Server(int port, ServerGUI sg) {
// GUI or not
this.sg = sg;
// the port
this.port = port;
// to display hh:mm:ss
sdf = new SimpleDateFormat("HH:mm:ss");
// ArrayList for the Client list
al = new ArrayList<ClientThread>();
}
public void start() {
keepGoing = true;
/* create socket server and wait for connection requests */
try
{
// the socket used by the server
ServerSocket serverSocket = new ServerSocket(port);
// infinite loop to wait for connections
while(keepGoing)
{
// format message saying we are waiting
display("Server waiting for Clients on port " + port + ".");
Socket socket = serverSocket.accept(); // accept connection
// if I was asked to stop
if(!keepGoing)
break;
ClientThread t = new ClientThread(socket); // make a thread of it
al.add(t); // save it in the ArrayList
t.start();
}
// I was asked to stop
try {
serverSocket.close();
for(int i = 0; i < al.size(); ++i) {
ClientThread tc = al.get(i);
try {
tc.sInput.close();
tc.sOutput.close();
tc.socket.close();
}
catch(IOException ioE) {
// not much I can do
}
}
}
catch(Exception e) {
display("Exception closing the server and clients: " + e);
}
}
// something went bad
catch (IOException e) {
String msg = sdf.format(new Date()) + " Exception on new ServerSocket: " + e + "\n";
display(msg);
}
}
/*
* For the GUI to stop the server
*/
protected void stop() {
keepGoing = false;
// connect to myself as Client to exit statement
// Socket socket = serverSocket.accept();
try {
new Socket("localhost", port);
}
catch(Exception e) {
// nothing I can really do
}
}
/*
* Display an event (not a message) to the console or the GUI
*/
private void display(String msg) {
String time = sdf.format(new Date()) + " " + msg;
if(sg == null)
System.out.println(time);
else
sg.appendRoom(null,time + "\n");
}
/*
* to broadcast a message to all Clients
*/
private synchronized void broadcast(String message) {
// add HH:mm:ss and \n to the message
String time = sdf.format(new Date());
String messageLf = time + " " + message + "\n";
// display message on console or GUI
if(sg == null)
System.out.print(messageLf);
else
sg.appendRoom(messageLf,null); // append in the room window
// we loop in reverse order in case we would have to remove a Client
// because it has disconnected
for(int i = al.size(); --i >= 0;) {
ClientThread ct = al.get(i);
// try to write to the Client if it fails remove it from the list
if(!ct.writeMsg(messageLf)) {
al.remove(i);
display("Disconnected Client " + ct.username + " removed from list.");
}
}
}
// for a client who logoff using the LOGOUT message
synchronized void remove(int id) {
// scan the array list until we found the Id
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
// found it
if(ct.id == id) {
al.remove(i);
return;
}
}
}
/*
* To run as a console application just open a console window and:
* > java Server
* > java Server portNumber
* If the port number is not specified 1500 is used
*/
public static void main(String[] args) {
// start server on port 1500 unless a PortNumber is specified
int portNumber = 1500;
switch(args.length) {
case 1:
try {
portNumber = Integer.parseInt(args[0]);
}
catch(Exception e) {
System.out.println("Invalid port number.");
System.out.println("Usage is: > java Server [portNumber]");
return;
}
case 0:
break;
default:
System.out.println("Usage is: > java Server [portNumber]");
return;
}
// create a server object and start it
Server server = new Server(portNumber);
server.start();
}
/** One instance of this thread will run for each client */
class ClientThread extends Thread {
// the socket where to listen/talk
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
// my unique id (easier for deconnection)
int id;
// the Username of the Client
String username;
// the only type of message a will receive
Message cm;
// the date I connect
String date;
// Constructore
ClientThread(Socket socket) {
// a unique id
id = ++uniqueId;
this.socket = socket;
/* Creating both Data Stream */
System.out.println("Thread trying to create Object Input/Output Streams");
try
{
// create output first
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
// read the username
username = (String) sInput.readObject();
display(username + " just connected.");
}
catch (IOException e) {
display("Exception creating new Input/output Streams: " + e);
return;
}
// have to catch ClassNotFoundException
// but I read a String, I am sure it will work
catch (ClassNotFoundException e) {
}
date = new Date().toString() + "\n";
}
// what will run forever
public void run() {
// to loop until LOGOUT
boolean keepGoing = true;
while(keepGoing) {
// read a String (which is an object)
try {
cm = (Message) sInput.readObject();
}
catch (IOException e) {
display(username + " Exception reading Streams: " + e);
break;
}
catch(ClassNotFoundException e2) {
break;
}
// the messaage part of the ChatMessage
String message = cm.getMessage();
// Switch on the type of message receive
switch(cm.getType()) {
case Message.MESSAGE:
broadcast(username + ": " + message);
break;
case Message.LOGOUT:
display(username + " disconnected with a LOGOUT message.");
keepGoing = false;
break;
case Message.ONLINE:
writeMsg("List of the users connected at " + sdf.format(new Date()) + "\n");
// scan al the users connected
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
writeMsg((i+1) + ") " + ct.username + " since " + ct.date);
}
break;
}
}
// remove myself from the arrayList containing the list of the
// connected Clients
remove(id);
close();
}
// try to close everything
private void close() {
// try to close the connection
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {}
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {};
try {
if(socket != null) socket.close();
}
catch (Exception e) {}
}
/*
* Write a String to the Client output stream
*/
private boolean writeMsg(String msg) {
// if Client is still connected send the message to it
if(!socket.isConnected()) {
close();
return false;
}
// write the message to the stream
try {
sOutput.writeObject(msg);
}
// if an error occurs, do not abort just inform the user
catch(IOException e) {
display("Error sending message to " + username);
display(e.toString());
}
return true;
}
}
}
ServerGUI
package Server;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
/*
* The server as a GUI
*/
public class ServerGUI extends JFrame implements ActionListener, WindowListener {
private static final long serialVersionUID = 1L;
// the stop and start buttons
private JButton stopStart, saveLog;
// JTextArea for the chat room and the events
private JTextArea chat;
// private JTextArea event;
// The port number
private JTextField tfPortNumber;
// my server
private Server server;
// server constructor that receive the port to listen to for connection as
// parameter
ServerGUI(int port) {
super("Chat Server");
server = null;
// in the NorthPanel the PortNumber the Start and Stop buttons
JPanel north = new JPanel();
north.add(new JLabel("Port number: "));
tfPortNumber = new JTextField("" + port);
north.add(tfPortNumber);
// to stop or start the server, we start with "Start"
stopStart = new JButton("Start");
stopStart.addActionListener(this);
saveLog = new JButton("Save log");
saveLog.addActionListener(this);
north.add(stopStart);
north.add(saveLog);
add(north, BorderLayout.NORTH);
// the event and chat room
JPanel center = new JPanel(new GridLayout());
chat = new JTextArea(120, 20);
chat.setEditable(false);
chat.setWrapStyleWord(true);
chat.setLineWrap(true);
appendRoom(null, "Chat room and Events log for server.\n");
center.add(new JScrollPane(chat));
// event = new JTextArea(80,80);
// event.setEditable(false);
// appendEvent("Events log.\n");
// center.add(new JScrollPane(event));
add(center);
// need to be informed when the user click the close button on the frame
addWindowListener(this);
setSize(450, 600);
setVisible(true);
}
public void writeLog() {
try {
JFileChooser chooser = new JFileChooser();
String content = chat.getText();
int actionDialog = chooser.showSaveDialog(this);
content = content.replaceAll("(?!\\r)\\n", "\r\n");
if (actionDialog == JFileChooser.APPROVE_OPTION) {
File file = new File(chooser.getSelectedFile() + ".txt");
// if file doesnt exists, then create it
// if (!file.exists()) {
// file.createNewFile();
// }
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
}
} catch (IOException ee) {
ee.printStackTrace();
}
// JFileChooser chooser = new JFileChooser();
// // chooser.setCurrentDirectory(new File("./"));
// int actionDialog = chooser.showSaveDialog(this);
// if (actionDialog == JFileChooser.APPROVE_OPTION) {
// File fileName = new File(chooser.getSelectedFile() + "");
// if (fileName == null)
// // return;
// if (fileName.exists()) {
// actionDialog = JOptionPane.showConfirmDialog(this,
// "Replace existing file?");
// if (actionDialog == JOptionPane.NO_OPTION)
// return;
// }
// try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
// new FileOutputStream(fileName), "ISO-8859-1"))) {
// bw.write(saveText);
// // bw.newLine();
// bw.flush();
// }
// }
}
// append message to the two JTextArea
// position at the end
void appendRoom(String chatStr, String eventStr) {
chat.append(chatStr);
chat.append(eventStr);
// chat.setCaretPosition(chat.getText().length() - 1);
}
// void appendEvent(String str) {
// event.append(str);
// event.setCaretPosition(chat.getText().length() - 1);
//
// }
// start or stop where clicked
public void actionPerformed(ActionEvent e) {
// if running we have to stop
if (e.getSource() == saveLog) {
writeLog();
} else if (e.getSource() == stopStart) {
if (server != null) {
server.stop();
server = null;
tfPortNumber.setEditable(true);
stopStart.setText("Start");
return;
}
// OK start the server
int port;
try {
port = Integer.parseInt(tfPortNumber.getText().trim());
} catch (Exception er) {
appendRoom(null, "Invalid port number");
return;
}
// ceate a new Server
server = new Server(port, this);
// and start it as a thread
new ServerRunning().start();
stopStart.setText("Stop");
tfPortNumber.setEditable(false);
}
}
/*
* A thread to run the Server
*/
class ServerRunning extends Thread {
public void run() {
server.start(); // should execute until if fails
// the server failed
stopStart.setText("Start");
tfPortNumber.setEditable(true);
appendRoom(null, "Server closed\n");
server = null;
}
}
// entry point to start the Server
public static void main(String[] arg) {
// start server default port 1500
new ServerGUI(1500);
}
/*
* If the user click the X button to close the application I need to close
* the connection with the server to free the port
*/
public void windowClosing(WindowEvent e) {
// if my Server exist
if (server != null) {
try {
server.stop(); // ask the server to close the conection
} catch (Exception eClose) {
}
server = null;
}
// dispose the frame
dispose();
System.exit(0);
}
// I can ignore the other WindowListener method
public void windowClosed(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
// /*
// * A thread to run the Server
// */
// class ServerRunning extends Thread {
// public void run() {
// server.start(); // should execute until if fails
// // the server failed
// stopStart.setText("Start");
// tfPortNumber.setEditable(true);
// appendRoom(null, "Server closed\n");
// server = null;
// }
// }
}
Message
package Server;
import java.io.Serializable;
//Klassen som kollar vad för typ av message
public class Message implements Serializable {
protected static final long serialVersionUID = 42L;
static final int ONLINE = 0;
static final int MESSAGE = 1;
static final int LOGOUT = 2;
private int SAVELOG = 3;
private String message;
private int type;
public Message(String message, int type){
this.type = type;
this.message = message;
}
public int getType(){
return type;
}
public String getMessage(){
return message;
}
}
Make your inner class ListenFromServer static, since you are referring to it from a static method
public class Controller {
...
public static class ListenFromServer {
...
}
}
sorry for posting a lot of code!!I don't know that why my ListFrame doesn't work???
these are the classes.At first I run the MainServer and then I will run the MainFrame in the other package.and then by inserting a correct user name and password ,the Listframe will be shown,BUT I click on menu bar or list or delete button but nothing will happen.why?? please help me.
MainSerevr class :
public class MainServer {
static Socket client = null;
static ServerSocket server = null;
public static void main(String[] args) {
System.out.println("Server is starting...");
System.out.println("Server is listening...");
try {
server = new ServerSocket(5050);
} catch (IOException ex) {
System.out.println("Could not listen on port 5050");
System.exit(-1);
}
try {
client = server.accept();
System.out.println("Client Connected...");
} catch (IOException e) {
System.out.println("Accept failed: 5050");
System.exit(-1);
}
try {
BufferedReader streamIn = new BufferedReader(new InputStreamReader(client.getInputStream()));
boolean done = false;
String line;
while (!done) {
line = streamIn.readLine();
if (line.equalsIgnoreCase(".bye")) {
done = true;
} else {
System.out.println("Client says: " + line);
}
}
streamIn.close();
client.close();
server.close();
} catch (IOException e) {
System.out.println("IO Error in streams " + e);
}
}}
ListFrame:
public class ListFrame extends javax.swing.JFrame implements PersonsModelChangeListener {
private InformationClass client;
private static DefaultListModel model = new DefaultListModel();
private ListSelectionModel moDel;
/** Creates new form ListFrame */
public ListFrame(InformationClass client) {
initComponents();
this.client = client;
jList1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fillTable();
Manager.addListener(this);
}
private void deleteAPerson() {
int index = jList1.getSelectedIndex();
String yahooId = (String) jList1.getSelectedValue();
model.remove(index);
Manager.removeApersonFromSQL(yahooId);
int size = model.getSize();
if (size == 0) {
jButton1.setEnabled(false);
} else {
if (index == size) {
index--;
}
jList1.setSelectedIndex(index);
jList1.ensureIndexIsVisible(index);
}
}
private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {
AddAPerson frame = new AddAPerson(client);
frame.setVisible(true);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
deleteAPerson();
}
private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {
MainClient.setText("");
MainClient.runAClient();
ChatFrame frame = new ChatFrame(client);
frame.setVisible(true);
}
public void fillTable() {
try {
List<InformationClass> list = null;
list = Manager.getClientListFromMySQL();
if (list == null) {
JOptionPane.showMessageDialog(this, "You should add a person to your list", "Information", JOptionPane.OK_OPTION);
return;
} else {
for (int i = 0; i < list.size(); i++) {
InformationClass list1 = list.get(i);
model.add(i, list1.getId());
}
jList1.setModel(model);
}
} catch (SQLException ex) {
Logger.getLogger(ListFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
MainClient class:
public class MainClient {
private static InformationClass info = new InformationClass();
private static Socket c;
private static String text;
public static String getText() {
return text;
}
public static void setText(String text) {
MainClient.text = text;
}
private static PrintWriter os;
private static BufferedReader is;
static boolean closed = false;
/**
* #param args the command line arguments
*/
public static void runAClient() {
try {
c = new Socket("localhost", 5050);
os = new PrintWriter(c.getOutputStream());
is = new BufferedReader(new InputStreamReader(c.getInputStream()));
String teXt = getText();
os.println(teXt);
if(c!=null&& is!=null&&os!=null){
String line = is.readLine();
System.out.println("Text received: " + line);
}
c.close();
is.close();
os.close();
} catch (UnknownHostException ex) {
System.err.println("Don't know about host");
} catch (Exception e) {
System.err.println("IOException: " + e);
}
}
}
EDIT:I have found the problem,which is because of writting MainClient.runAClient() in code ,where should I put it? please help me.
This article contains an sscce that illustrates a simple client-server GUI. You may find it instructive. If so, consider how you would address the bug found in the last line of the Echo(Kind kind) constructor.