I'm trying to create a server/client for the purpose of chatting. I start the server which waits for a client to connect, the client connects, but it gets stuck waiting for the client to send the username.
Here is the server:
package chat_server;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Chat_Server {
private ServerSocket ss;
private Socket connection;
private List<ClientT> users;
private static int usersNumber;
public Chat_Server() {
users = new ArrayList<ClientT>();
usersNumber = 1;
try {
ss = new ServerSocket(2016);
} catch (IOException e) {
e.printStackTrace();
System.err.println(3);
}
}
public void acceptRequests() throws IOException {
while (true) {
try {
connection = ss.accept();
ClientT ct = new ClientT(connection);
users.add(ct);
System.out.print("Connected users: ");
for(int i = 0; i < users.size(); i++)
System.out.print(users.get(i) + " ");
System.out.println();
ct.start();
} catch (IOException e) {
System.out.println("Could not accept connection from client: "
+ e);
System.err.println(4);
}
}
}
}
class ClientT extends Thread {
private Socket s;
private BufferedReader in;
private DataOutputStream out;
private String userName = "a";
private String message;
int userNr;
public ClientT(Socket _s) {
this.s = _s;
userNr = usersNumber++;
System.out.println("In client: s = " + s + " userNr = " + userNr);
try {
System.out.println("Creating 'in' and 'out' objects");
out = new DataOutputStream(s.getOutputStream());
in = new BufferedReader(new InputStreamReader(
s.getInputStream()));
System.out.println("Catching username...");
**//--it gets stuck here--**
userName = (String) in.readLine();
System.out.println(userName + " connected...");
} catch (IOException e) {
e.printStackTrace();
System.err.println(1);
}
}
public void run() {
System.out.println("In ClientT run...");
while (true) {
try {
message = in.readLine();
System.out.println("Message: " + message);
System.out.println("Notifying all clients!");
messageNotifyAll(message);
} catch (IOException e) {}
}
}
}
public static void main(String[] args) throws IOException {
Chat_Server cs = new Chat_Server();
System.out.println("Accepting requests...");
cs.acceptRequests();
}
}
And here the the client:
package chatClient;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.*;
#SuppressWarnings("serial")
public class Client extends JFrame {
private JTextArea textArea;
private JScrollPane scrollPane;
private JPanel panelButtons;
private JPanel panelList;
private JButton send;
private JButton disconnect;
#SuppressWarnings("rawtypes")
private JList userList;
private JLabel connectedUsers;
private JTextField text;
private JButton sendMessage;
private String name;
private Socket s;
BufferedReader in;
DataOutputStream out;
#SuppressWarnings("rawtypes")
public Client(String _name) throws InterruptedException {
System.out.println("Loading GUI...");
//GUI left out
System.out.println("Loading GUI finished...");
connectToServer();
}
public void connectToServer() throws InterruptedException {
try {
textArea.append("Connecting to server...\n");
s = new Socket("localhost", 2016);
textArea.append("Connected to " + s.getInetAddress() + ":" + s.getPort() +" as " + name + "...");
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new DataOutputStream(s.getOutputStream());
new waitForMessage().start();
out.writeBytes(name);
} catch (UnknownHostException e) {
textArea.append("Server not running!");
// e.printStackTrace();
} catch (IOException e) {
textArea.append(e + "\n");
try {
disconnectFromServer();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public void disconnectFromServer() throws IOException {
s.close();
System.out.println("Disconnected!");
}
public class FrameExit extends WindowAdapter {
public void windowClosing(WindowEvent e) {
e.getWindow().dispose();
}
}
public class Disconnect implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
s.close();
System.out.println("Disconnecting...");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public class Send implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
System.out.println("Sending message: " + text.getText());
out.writeBytes(text.getText());
text.setText("");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public class waitForMessage extends Thread {
#Override
public void run() {
System.out.println("Waiting for message!");
while (true) {
try {
String message = in.readLine();
System.out
.println("Message received! Displaying message in GUI!");
textArea.append(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
//I have a login GUI from where I start the Client
}
}
Any help would be appreciated!
Server side seems to expect a line to read, but there is no line break sent from the client side.
Also, consider adding out.flush() after you write, to ensure that the data is actually sent.
out.writeBytes(name + System.getProperty("line.separator"));
out.flush();
Note that you could use a PrintWriter instead, which has println methods to take care of new lines.
See : What is the Difference between PrintWriter and DataOutputStream?
Related
I have Honeywell USB barcode scanner. I want to read input of barcode scanner by using Java code.
I got solution by below code but i dont want to use any gui.
import java.awt.AWTEvent;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class BarcodeScaner extends JFrame {
private static String strBarcode = "";
private static JTextField jtBarcode = new JTextField(25);
public BarcodeScaner() {
getContentPane().setLayout(new FlowLayout());
getContentPane().add(new JLabel("Capture barcode "));
getContentPane().add(jtBarcode);
}
public static void main(String[] args) {
BarcodeScaner br = new BarcodeScaner();
readBarCode();
br.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
br.setVisible(true);
br.pack();
}
private static void readBarCode() {
// start of listening for barcode events
Toolkit.getDefaultToolkit().addAWTEventListener(new BarcodeAwareAWTEventListener(new BarcodeCapturedListener() {
#Override
public void barcodeCaptured(String barcode) {
strBarcode = barcode;
System.out.println("====="+barcode);
jtBarcode.setText(strBarcode);
}
}), AWTEvent.KEY_EVENT_MASK);
// end of listening for barcode events
}
}
In above code i have to focus on textbox then only i get scanned value.
I have search in stackoverflow but i didnt get any specific solution.
I also try this below code but still serialEvent is not execute.
package scanhandler;
import java.awt.AWTException;
import java.awt.Robot;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Enumeration;
import java.util.Properties;
import java.util.TooManyListenersException;
import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;
public class ScanHandler implements Runnable, SerialPortEventListener {
private static CommPortIdentifier myCommPortIdentifier;
private static Enumeration portList;
private static String TimeStamp;
private static String driverClass;
private static String connectionString;
private static String comPort;
private Connection myConnection;
private InputStream myInputStream;
private Robot myRobot;
private SerialPort mySerialPort;
private Thread myThread;
public ScanHandler() {
// open serial port
try {
TimeStamp = new java.util.Date().toString();
mySerialPort = (SerialPort) myCommPortIdentifier.open("ComControl", 2000);
//System.out.println(TimeStamp + ": " + myCommPortIdentifier.getName() + " opened for scanner input");
} catch (PortInUseException e) {
e.printStackTrace();
}
// get serial input stream
try {
myInputStream = mySerialPort.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
// add an event listener on the port
try {
mySerialPort.addEventListener(this);
} catch (TooManyListenersException e) {
e.printStackTrace();
}
mySerialPort.notifyOnDataAvailable(true);
// set up the serial port properties
try {
mySerialPort.setSerialPortParams(9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
mySerialPort.setDTR(false);
mySerialPort.setRTS(false);
} catch (UnsupportedCommOperationException e) {
e.printStackTrace();
}
// make a robot to pass keyboard data
try {
myRobot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
// create the thread
myThread = new Thread(this);
myThread.start();
}
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
// on scan
public void serialEvent(SerialPortEvent event) {
if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
StringBuilder myStringBuilder = new StringBuilder();
int c;
try {
// append the scanned data onto a string builder
while ((c = myInputStream.read()) != 10){
if (c != 13) myStringBuilder.append((char) c);
}
// send to keyboard buffer if it the barcode doesn't start with '5'
if (myStringBuilder.charAt(0) != '5') {
for (int i = 0; i < myStringBuilder.length(); i++) {
myRobot.keyPress((int) myStringBuilder.charAt(i));
myRobot.keyRelease((int) myStringBuilder.charAt(i));
}
// here's the scanned barcode as a variable!
} else {
TimeStamp = new java.util.Date().toString();
System.out.println(TimeStamp + ": scanned input received:" + myStringBuilder.toString());
}
// close the input stream
myInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// read ScanHandler properties
Properties myProperties = new Properties();
try {
myProperties.load(new FileInputStream("config.properties"));
comPort = myProperties.getProperty("ScanHandler.comPort");
} catch (IOException e) {
e.printStackTrace();
}
try {
// get our pre-defined COM port
myCommPortIdentifier = CommPortIdentifier.getPortIdentifier(comPort);
ScanHandler reader = new ScanHandler();
} catch (Exception e) {
TimeStamp = new java.util.Date().toString();
System.out.println(TimeStamp + ": " + comPort + " " + myCommPortIdentifier);
System.out.println(TimeStamp + ": msg1 - " + e);
}
};
}
Please set the scanner to USB Serial mode by using the setting barcode stated in the user's guide.
Then install the serial port device driver of the OS of the machine to which the scanner is connected.
Then you can open the serial port and send commands to the scanner and receive barcode data.
I am creating a multiclient chat server program. Messages are sent as Message objects. The ServerClient class is not recieving the messages, though, and I don't know why.
Client:
package client;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.*;
import constraints.Constraints;
import message.Message;
import tools.Tools;
import window.ApplicationWindow;
#SuppressWarnings("serial")
public class Client extends ApplicationWindow {
private static final int portNumber = 4444;
private boolean send = false;
private String userName;
private String serverHost;
private int serverPort;
private GridBagLayout layout;
private JTextArea textArea;
private Constraints c_textArea;
private JTextField textField;
private Constraints c_textField;
public static void main(String[] args){
String readName = System.getProperty("user.name");
Client client = new Client(readName, portNumber);
client.startClient();
}
private Client(String userName, int portNumber){
super("ChatApp");
Tools.setLookAndFeel();
this.userName = userName;
this.serverPort = portNumber;
try {
this.serverHost = InetAddress.getLocalHost().getHostAddress();
}catch(Exception e) {
}
layout = new GridBagLayout();
setLayout(layout);
textArea = new JTextArea();
textArea.setColumns(75);
textArea.setRows(20);
c_textArea = new Constraints(0,1);
textArea.setLineWrap(true);
textArea.setEditable(false);
textArea.setVisible(true);
JScrollPane scroll = new JScrollPane (textArea);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scroll, c_textArea);
textField = new JTextField();
textField.setColumns(50);
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send = true;
}
});
c_textField = new Constraints(0,2);
add(textField, c_textField);
pack();
setVisible(true);
setResizable(false);
}
public void output(String message) {
this.textArea.setText(this.textArea.getText() + "\n" + message);
}
private void startClient() {
try{
Socket socket = new Socket(serverHost, serverPort);
Thread.sleep(1000);
ServerThread serverThread = new ServerThread(socket, userName, this);
Thread serverAccessThread = new Thread(serverThread);
serverAccessThread.start();
while(serverAccessThread.isAlive() && this.isRunning()) {
if (send) {
Message message = new Message(textField.getText(), "[" + "]", this.userName);
serverThread.addNextMessage(message);
send = false;
textField.setText("");
}
Thread.sleep(200);
}
}catch(IOException ex){
output("Could not connect to server!");
}catch(InterruptedException ex){
output("Connection interrupted!");
}
}
public void setHost(String serverHost) {
this.serverHost = serverHost;
}
}
ServerClient:
package server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;
import message.Message;
public class ServerClient implements Runnable {
private Socket socket;
private PrintWriter clientOut;
private ChatServer server;
private boolean running;
public ServerClient(ChatServer server, Socket socket) {
this.server = server;
this.socket = socket;
this.running = true;
}
private PrintWriter getWriter(){
return clientOut;
}
public boolean isRunning() {
return this.running;
}
public void stop() {
this.running = false;
}
#Override
public void run() {
try{
this.clientOut = new PrintWriter(socket.getOutputStream(), false);
clientOut.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
while(!socket.isClosed()){
try {
if (in.available() > 0) {
Object i = in.readObject();
if (!i.equals(null)) {
Message input = (Message) i;
String message = input.getText();
String time = input.getTimestamp();
String user = input.getUser();
for(ServerClient thatClient : server.getClients()){
PrintWriter thatClientOut = thatClient.getWriter();
if(thatClientOut != null){
thatClientOut.write(time + " " + user + ": " + message + "\r\n");
thatClientOut.flush();
}
}
}
}
} catch (ClassNotFoundException e) {
System.out.println(e);
} catch (SocketException ex) {
System.out.println(ex);
break;
}
}
in.close();
this.stop();
} catch (IOException e) {
e.printStackTrace();
}
}
//public void fileWrite()
}
ChatServer:
package server;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
//import javax.swing.JComboBox;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import constraints.Constraints;
import tools.Tools;
import window.ApplicationWindow;
import message.Message;
#SuppressWarnings("serial")
public class ChatServer extends ApplicationWindow {
private static final int portNumber = 4444;
private ArrayList<Command> commands;
private int serverPort;
private String serverHost;
private List<ServerClient> clients;
ServerSocket serverSocket;
private GridBagLayout layout;
private JTextArea textArea;
private Constraints c_textArea;
private JTextField textField;
private Constraints c_textField;
public static void main(String[] args){
ChatServer server = new ChatServer(portNumber);
server.startServer();
}
public ChatServer(int portNumber){
super("Server " + portNumber);
this.serverPort = portNumber;
try {
this.serverHost = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
this.serverHost = "";
}
Tools.setLookAndFeel();
initActions();
layout = new GridBagLayout();
setLayout(layout);
textArea = new JTextArea();
textArea.setColumns(75);
textArea.setRows(20);
c_textArea = new Constraints(0,1);
textArea.setLineWrap(true);
textArea.setEditable(false);
textArea.setVisible(true);
JScrollPane scroll = new JScrollPane (textArea);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scroll, c_textArea);
textField = new JTextField();
textField.setColumns(50);
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
process(textField.getText());
}
});
c_textField = new Constraints(0,2);
add(textField, c_textField);
pack();
setVisible(true);
setResizable(false);
}
public List<ServerClient> getClients(){
return clients;
}
private void startServer(){
clients = new ArrayList<ServerClient>();
serverSocket = null;
try {
InetAddress addr = InetAddress.getByName(this.serverHost);
serverSocket = new ServerSocket(serverPort, 50, addr);
acceptClients(serverSocket);
} catch (IOException e){
output("[ERROR] COULD NOT LISTEN ON PORT: " + serverPort);
this.stop();
}
}
private void acceptClients(ServerSocket serverSocket){
output("[BEGIN] SERVER STARTING ON PORT: " + serverSocket.getLocalSocketAddress());
while (this.isRunning()) {
try{
Socket socket = serverSocket.accept();
output("[ACCEPT] ACCEPTED CLIENT AT: " + socket.getRemoteSocketAddress());
ServerClient client = new ServerClient(this, socket);
Thread thread = new Thread(client);
thread.start();
clients.add(client);
} catch (IOException ex) {
output("[ERROR] ACCEPT FAILED ON: " + serverPort);
}
}
}
private void initActions() {
this.commands = new ArrayList<Command>();
this.commands.add(new Command() {
public void run() {
output("[COMMAND] IP: " + serverSocket.getInetAddress().toString());
}
public String getTrigger() {
return "-ip";
}
});
this.commands.add(new Command() {
public void run() {
for (ServerClient client : clients) {
if (!client.isRunning()) {
clients.remove(client);
}
}
output("[COMMAND] CLIENTS: " + clients.size());
}
public String getTrigger() {
return "-clients";
}
});
}
public boolean process(String command) {
for (Command c : this.commands) {
if (c.getTrigger().equals(command)) {
c.run();
textField.setText("");
return true;
}
}
return false;
}
public void output(String message) {
this.textArea.setText(this.textArea.getText() + "\n" + message);
}
}
ServerThread:
package client;
import java.io.*;
import java.net.Socket;
import java.util.LinkedList;
import java.util.Scanner;
import message.Message;
#SuppressWarnings("unused")
public class ServerThread implements Runnable {
private Socket socket;
private String userName;
private boolean isAlived;
private final LinkedList<Message> messagesToSend;
private boolean hasMessages = false;
private Client client;
public ServerThread(Socket socket, String userName, Client client){
this.socket = socket;
this.userName = userName;
this.client = client;
messagesToSend = new LinkedList<Message>();
}
public void addNextMessage(Message message) {
synchronized (messagesToSend) {
hasMessages = true;
messagesToSend.push(message);
}
}
#Override
public void run(){
print("Welcome :" + userName);
print("Local Port :" + socket.getLocalPort());
print("Server = " + socket.getRemoteSocketAddress() + ":" + socket.getPort());
try {
ObjectOutputStream serverOut = new ObjectOutputStream(socket.getOutputStream());
serverOut.flush();
ObjectInputStream serverIn = new ObjectInputStream(socket.getInputStream());
while(!socket.isClosed()){
if (serverIn.available() > 0) {
try {
if (serverIn.readObject() != null) {
Message input = (Message) serverIn.readObject();
}
} catch (ClassNotFoundException e) {
System.out.println(e);
}
}
if(hasMessages){
Message nextSend;
synchronized(messagesToSend){
nextSend = messagesToSend.pop();
hasMessages = !messagesToSend.isEmpty();
}
serverOut.writeObject(nextSend);
serverOut.flush();
}
}
serverOut.close();
serverIn.close();
} catch(Exception ex){
ex.printStackTrace();
}
}
public void print(String message) {
this.client.output(message);
}
}
I know that the client is able to connect to the server, and both can get messages and successfully call the writeObject() method. However, the message never gets recieved. Can someone help me?
while(!socket.isClosed()){
if (serverIn.available() > 0) {
try {
if (serverIn.readObject() != null) {
Message input = (Message) serverIn.readObject();
}
} catch (ClassNotFoundException e) {
System.out.println(e);
}
}
if(hasMessages){
Message nextSend;
synchronized(messagesToSend){
nextSend = messagesToSend.pop();
hasMessages = !messagesToSend.isEmpty();
}
serverOut.writeObject(nextSend);
serverOut.flush();
}
}
This is all nonsense.
isClosed() returns true when you have closed the socket. Not when the peer disconnects.
Calling available() here and merely spin-looping while it is false is just literally a waste of time.
ObjectInputStream.readObect() only returns null if you send a null.
You are calling it twice, throwing the first object read away, and then trying to read the next object. So you are throwing away every odd-numbered object.
It should be more like this:
for (;;) {
try {
Message input = (Message) serverIn.readObject();
// process input here
} catch (EOFException e) {
break;
} catch (ClassNotFoundException e) {
System.out.println(e);
}
}
if(hasMessages){
Message nextSend;
synchronized(messagesToSend){
nextSend = messagesToSend.pop();
hasMessages = !messagesToSend.isEmpty();
}
serverOut.writeObject(nextSend);
serverOut.flush();
}
}
You should probably split this into a reading thread and a writing thread, as writeObject() and flush() can also block. Same remarks apply to the other place where you are using isClosed(), available(), testing for null, etc.
The hasMessages flag is also not going to work. It will remain false even though a message got added subsequently. It would be better to delete it and just rely on messagesToSend.isEmpty(), inside a synchronized block:
synchronized(messagesToSend){
while (!messagesToSend.isEmpty()){
Message nextSend = messagesToSend.pop();
serverOut.writeObject(nextSend);
}
}
serverOut.flush();
I am trying to a simple client server chat application using Stream sockets and Swing. But it is not working as it should. Apparently the server just waits for connection and does not proceed.
I have three java files, Server.java , Client.java and ChatApp.java
Server.java
package com.htpj.networkingChatApp;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Server extends JFrame {
private static final long serialVersionUID = 1L;
private JTextArea displayArea;
private JTextField messageEnterField;
private ServerSocket server;
private Socket connectionSocket;
private ObjectInputStream input;
private ObjectOutputStream output;
private int counter = 1;
protected void serverGui() {
messageEnterField = new JTextField();
setMessageEnterFieldEditable(false);
messageEnterField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendDataToClient(e.getActionCommand());
}
});
add(messageEnterField, BorderLayout.SOUTH);
displayArea = new JTextArea();
add(new JScrollPane(displayArea), BorderLayout.CENTER);
displayArea.setEditable(false); // display area is never editable
setSize(500, 500);
setLocationRelativeTo(null);
setTitle("Chat Server");
setVisible(true);
}
protected void runServer() {
try {
server = new ServerSocket(2000, 100);
while (true) {
try {
waitForConnection(); // wait for a connection
getStreams(); // get input and output streams
processConnection(); // process connections
} catch (EOFException e) {
displayMessage("\n server terminated the connection");
} finally {
closeConnection();
++counter;
}
}
} catch (IOException e) {
e.printStackTrace();
}
} // ENDOF method runServer
private void waitForConnection() {
try {
displayMessage("Waiting for Connection\n");
connectionSocket = server.accept();
displayMessage("Connection" + counter + "received from: " + connectionSocket.getInetAddress() + "port: "
+ connectionSocket.getPort());
} catch (IOException e) {
e.printStackTrace();
}
} // ENDOF method waitForConnection
private void getStreams() throws IOException {
output = new ObjectOutputStream(connectionSocket.getOutputStream());
output.flush(); // flush output buffer to send header information
input = new ObjectInputStream(connectionSocket.getInputStream());
displayMessage("\n Got I/O Streams \n");
} // ENDOF getStreams method
private void processConnection() throws IOException {
String message = null;
sendDataToClient("Connection Successful \n");
setMessageEnterFieldEditable(true); // enable server to type message
do {
try {
message = (String) input.readObject();
displayMessage("\n" + message);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} while (!message.equals("CLIENT >> TERMINATE"));
} // ENDOF processConnection method
private void closeConnection() {
displayMessage("\n closing connection \n");
setMessageEnterFieldEditable(false);
try {
output.close();
input.close();
connectionSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
} // ENDOF closeConnection method
private void sendDataToClient(String messageFromServer) {
try {
output.writeObject("SERVER>> " + messageFromServer);
output.flush(); // flush output to client
} catch (IOException e) {
e.printStackTrace();
}
} // ENDOF sendDataToClient method
private void displayMessage(String showMessage) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
displayArea.append(showMessage);
}
});
} // ENDOF method displayMessage
private void setMessageEnterFieldEditable(final boolean isEditable) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
messageEnterField.setEditable(isEditable);
}
});
}
} // ENDOF class server
Client.java
package com.htpj.networkingChatApp;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Client extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField messageEnterField;
private JTextArea displayArea;
private String chatHost;
private Socket clientSocket;
private ObjectInputStream input;
private ObjectOutputStream output;
private String message = "";
public Client(String host) {
this.chatHost = host;
}
protected void clientGui() {
messageEnterField = new JTextField();
setMessageEnterFieldEditable(false);
messageEnterField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendDataToServer(e.getActionCommand());
}
});
add(messageEnterField, BorderLayout.SOUTH);
displayArea = new JTextArea();
add(new JScrollPane(displayArea), BorderLayout.CENTER);
displayArea.setEditable(false);
setTitle("Chat Client");
setSize(500, 500);
setLocationRelativeTo(null);
setVisible(true);
} // END OF clientGui method
// connect to the server and process message from server
protected void runClient() throws UnknownHostException, IOException, ClassNotFoundException {
// connect to server, get Streams, process connection
try {
connectToServer();
getStreams();
processConnection();
} catch (EOFException e) {
displayMessage("\n client closed the connection");
} finally {
closeConnection();
}
}
private void connectToServer() throws UnknownHostException, IOException {
displayMessage("Attempting Connection to Server: \n");
clientSocket = new Socket(InetAddress.getByName(chatHost), 2000);
displayMessage(
"Connected to: " + clientSocket.getInetAddress().getHostName() + "on Port : " + clientSocket.getPort());
} // END OF method connectToServer
private void getStreams() throws IOException {
output = new ObjectOutputStream(clientSocket.getOutputStream());
output.flush();
input = new ObjectInputStream(clientSocket.getInputStream());
displayMessage("\n Got I/O stream \n ");
} // END OF getStreams method
private void processConnection() throws ClassNotFoundException, IOException {
displayMessage("\n connected to server\n");
setMessageEnterFieldEditable(true);
do {
message = (String) input.readObject();
displayMessage("\n" + message);
} while (!message.equals("SERVER>> TERMINATE"));
} // end of processConnection method
private void closeConnection() throws IOException {
displayMessage("\n closing connection ");
input.close();
output.close();
clientSocket.close();
setMessageEnterFieldEditable(false);
} // end of closeConnection method
private void displayMessage(final String messageToShow) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
displayArea.append(messageToShow);
}
});
} // end of displayMessage method
private void sendDataToServer(String messageToServer) {
try {
output.writeObject(messageToServer);
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
} // end of sendDataToServer method
private void setMessageEnterFieldEditable(final boolean isEditable) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
messageEnterField.setEditable(isEditable);
}
});
}
}
ChatApp.java
package com.htpj.networkingChatApp;
import java.io.IOException;
public class ChatApp{
public static void main(String[] args) {
Server chatServer = new Server();
Client chatClient = new Client("127.0.0.1");
chatServer.serverGui();
chatClient.clientGui();
chatServer.runServer();
try {
chatClient.runClient();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
}
}
I create chat app one to one by using Java programming language
I faced issue: client can't send a new message until he receives a message from the server.
You should have a multithreaded application.
The client will run 2 threads:
1) Sender thread which will run on send button. You can every time create a new instance of this thread on clicking send button.
2) The receiver thread will keep on running continuously and check the stream for any message. Once it gets a message on stream it will write the same on console.
Will update you shortly with the code.
Thanks
Written this code long back similarly you can write server using other port
package com.clients;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ClientFullDuplex extends JFrame implements ActionListener {
private JFrame jframe;
private JPanel jp1, jp2;
private JScrollPane jsp;
private JTextArea jta;
private JTextField jtf;
private JButton send;
private Thread senderthread;
private Thread recieverthread;
private Socket ds;
private boolean sendflag;
public static void main(String[] args) {
try {
ClientFullDuplex sfd = new ClientFullDuplex();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public ClientFullDuplex() throws UnknownHostException, IOException {
initGUI();
ds = new Socket("127.0.0.1", 1124);
initNetworking();
}
public void initGUI() {
jframe = new JFrame();
jframe.setTitle("Client");
jframe.setSize(400, 400);
jp1 = new JPanel();
jta = new JTextArea();
jsp = new JScrollPane(jta);
jtf = new JTextField();
send = new JButton("Send");
send.addActionListener(this);
jp1.setLayout(new GridLayout(1, 2, 10, 10));
jp1.add(jtf);
jp1.add(send);
jframe.add(jp1, BorderLayout.SOUTH);
jframe.add(jsp, BorderLayout.CENTER);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jta.append("hello client");
}
#Override
public synchronized void addWindowListener(WindowListener arg0) {
// TODO Auto-generated method stub
super.addWindowListener(arg0);
new WindowAdapter() {
#Override
public void windowClosing(WindowEvent arg0) {
// TODO Auto-generated method stub
if (ds != null)
try {
ds.close();
System.exit(0);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}
public void initNetworking() {
try {
recieverthread = new Thread(r1);
recieverthread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
Runnable r1 = new Runnable() {
#Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()
+ "Reciver Thread Started");
recieveMessage(ds);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()
+ "Sender Thread Started");
sendMessage(ds);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
public void recieveMessage(Socket rms) throws IOException {
while (true) {
System.out.println(Thread.currentThread().getName()
+ "Reciver Functionality");
BufferedReader br = new BufferedReader(new InputStreamReader(
rms.getInputStream()));
String line = br.readLine();
System.out.println(line);
jta.append("\nServer:"+line);
}
}
public void sendMessage(Socket sms) throws IOException {
System.out.println(Thread.currentThread().getName()
+ "Sender Functionality");
PrintWriter pw = new PrintWriter(sms.getOutputStream(), true);
String sline = jtf.getText();
System.out.println(sline);
pw.println(sline);
jtf.setText("");
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource() == send) {
senderthread = new Thread(r2);
senderthread.start();
}
}
}
This is the code I copied and edited from your earlier post.
The problem is that the input stream from socket is blocking. So my suggestion is to read up on async sockets in java and refactor the code below.
next to that it isn't that difficult to edit posts.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
public static void main(String[] args) {
Server chatServer = new Server(5555);
System.out.println("###Start listening...###");
chatServer.startListening();
chatServer.acceptClientRequest();
}
private ServerSocket listeningSocket;
private Socket serviceSocket;
private int TCPListeningPort;
private ArrayList<SocketHanding> connectedSocket;
public Server(int TCPListeningPort)
{
this.TCPListeningPort = TCPListeningPort;
connectedSocket = new ArrayList<SocketHanding>();
}
public void startListening()
{
try
{
listeningSocket = new ServerSocket(TCPListeningPort);
}
catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void acceptClientRequest()
{
try
{
while (true)
{
serviceSocket = listeningSocket.accept();
SocketHanding _socketHandling = new SocketHanding(serviceSocket);
connectedSocket.add(_socketHandling);
Thread t = new Thread(_socketHandling);
t.start();
System.out.println("###Client connected...### " + serviceSocket.getInetAddress().toString() );
}
}
catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
class SocketHanding implements Runnable
{
private Socket _connectedSocket;
private PrintWriter socketOut;
private InputStream socketIn;
private boolean threadRunning = true;
private String rmsg;
public SocketHanding(Socket connectedSocket) throws IOException
{
_connectedSocket = connectedSocket;
socketOut = new PrintWriter(_connectedSocket.getOutputStream(), true);
socketIn = _connectedSocket.getInputStream();
}
private void closeConnection() throws IOException
{
threadRunning = false;
socketIn.close();
socketOut.close();
_connectedSocket.close();
}
public void sendMessage(String message)
{
socketOut.println(message);
}
private String receiveMessage() throws IOException
{
String t = "";
if (_connectedSocket.getInputStream().available() > 0)
{
byte[] b = new byte[8192];
StringBuilder builder = new StringBuilder();
int bytesRead = 0;
if ( (bytesRead = _connectedSocket.getInputStream().read(b)) > -1 )
{
builder.append(new String(b, 0, b.length).trim());
}
t = builder.toString();
}
return t;
}
#Override
public void run()
{
while (threadRunning)
{
try
{
rmsg = receiveMessage();
System.out.println(rmsg);
if(rmsg.equalsIgnoreCase("bye"))
{
System.out.println("###...Done###");
closeConnection();
break;
}
else
{
String smsg = "";
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
smsg = keyboard.readLine();
keyboard.close();
sendMessage("Server: "+smsg);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
As I am learning java socket, I've made a functionnal but very simple chat in two frames : one client and one server. The app is only local and works. But it does not stop when I close windows (though I added WindowListener to both frame classes) : what's wrong ?
Don't forget to run the server first, and then the client : both frames will be visibles only after the client connection.
Here is SimpleSocketFrame.java (base class for both frames) :
package com.loloof64.java_se.simple_socket;
import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public abstract class SimpleSocketFrame extends JFrame {
public SimpleSocketFrame() {
setTitle(getFrameTitle());
setLayout(new GridLayout(0, 1));
messageToAddField = new JTextField(30);
messageToAddField.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER){
if ( ! messageToAddField.getText().isEmpty()) {
addMessage(messageToAddField.getText());
messageToAddField.setText("");
}
}
}
});
printedMessagesArea = new JTextArea(10,30);
printedMessagesArea.setEditable(false);
add(messageToAddField);
add(printedMessagesArea);
pack();
}
protected abstract void addMessage(String s);
protected abstract String getFrameTitle();
private static final long serialVersionUID = -5861605385948623162L;
protected JTextArea printedMessagesArea;
private JTextField messageToAddField;
}
Here is the server app class : SimpleSocketServer.java
package com.loloof64.java_se.simple_socket;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JOptionPane;
public class SimpleSocketServer extends SimpleSocketFrame {
public SimpleSocketServer(){
super();
setTitle("Simple Server");
try {
serverSocket = new ServerSocket(12345);
relatedSocket = serverSocket.accept();
outStream = new PrintStream(relatedSocket.getOutputStream());
isr = new InputStreamReader(relatedSocket.getInputStream());
inStream = new BufferedReader(isr);
final InStreamRunnable inStreamRunnable = new InStreamRunnable();
Thread inStreamReaderThread = new Thread(inStreamRunnable);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent evt) {
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
outStream.close();
try {
relatedSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
inStreamRunnable.stop();
System.exit(0);
}
});
inStreamReaderThread.start();
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Could not create the server !!!",
"Fatal error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
e.printStackTrace();
}
}
private class InStreamRunnable implements Runnable {
#Override
public void run() {
while (weMustGoOn){
String line;
try {
line = inStream.readLine();
printedMessagesArea.setText(printedMessagesArea.getText()+line+"\n");
} catch (IOException e) {
}
}
}
public void stop(){
weMustGoOn = false;
}
private boolean weMustGoOn = true;
}
#Override
protected void addMessage(String s) {
s = "Serveur> "+s;
outStream.println(s);
printedMessagesArea.setText(printedMessagesArea.getText()+"Client> "+s+"\n");
}
#Override
protected String getFrameTitle() {
return "Simple Server";
}
public static void main(String[] args) {
new SimpleSocketServer().setVisible(true);
}
private static final long serialVersionUID = 4288994465786972478L;
private Socket relatedSocket;
private ServerSocket serverSocket;
private PrintStream outStream;
private InputStreamReader isr;
private BufferedReader inStream;
}
Here is the client class : SimpleSocketClient.java
package com.loloof64.java_se.simple_socket;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import javax.swing.JOptionPane;
public class SimpleSocketClient extends SimpleSocketFrame {
public SimpleSocketClient(){
try {
socket = new Socket(InetAddress.getLocalHost(), 12345);
outStream = new PrintStream(socket.getOutputStream());
isr = new InputStreamReader(socket.getInputStream());
inStream = new BufferedReader(isr);
final InStreamRunnable inStreamRunnable = new InStreamRunnable();
Thread inStreamReaderThread = new Thread(inStreamRunnable);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent evt) {
try {
inStream.close();
} catch (IOException e2) {
e2.printStackTrace();
}
try {
isr.close();
} catch (IOException e1) {
e1.printStackTrace();
}
outStream.close();
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
inStreamRunnable.stop();
System.exit(0);
}
});
inStreamReaderThread.start();
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Could not create the client !!!",
"Fatal error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
e.printStackTrace();
}
}
public static void main(String[] args) {
new SimpleSocketClient().setVisible(true);
}
private class InStreamRunnable implements Runnable {
#Override
public void run() {
while (weMustGoOn){
String line;
try {
line = inStream.readLine();
printedMessagesArea.setText(printedMessagesArea.getText()+line+"\n");
} catch (IOException e) {
}
}
}
public void stop(){
weMustGoOn = false;
}
private boolean weMustGoOn = true;
}
#Override
protected void addMessage(String s) {
s = "Client> "+s;
outStream.println(s);
printedMessagesArea.setText(printedMessagesArea.getText()+s+"\n");
}
#Override
protected String getFrameTitle() {
return "Simple Client";
}
private static final long serialVersionUID = 5468568598525947366L;
private Socket socket;
private PrintStream outStream;
private InputStreamReader isr;
private BufferedReader inStream;
}
The program doesn't stop as you're attempting to close the network input Readers when closing a JFrame, which are blocking indefinitely. BufferedReader and InputStreamReader objects cannot close as the client thread is blocked in this readLine call which is waiting for a response from the server
line = inStream.readLine();
Comment out or remove:
inStream.close();
and
isr.close();
Just closing the Socket stream will suffice.
Aside: When interacting with Swing components for multi-threaded network applications, always use a SwingWorker. SwingWorkers are designed to interact correctly with Swing components.
You should add finally block after try and catch to close the socket and after that you can close your program by system exit method.