Client/Server Chat app with file transfer JAVA Sockets - java

I am new to java and I made a chat application through which client and server can send and receive messages, now I was trying to send a file from client to server but after the file is received by server , client and server both cant send messages , Here is the code :
Client Side :
import java.io.*;
import java.net.*;
import javax.swing.JFileChooser;
public class ClientFrame extends javax.swing.JFrame {
static Socket s;
static DataOutputStream dos1;
static DataInputStream dis;
static javax.swing.JTextArea jT;
static JFileChooser fc = new JFileChooser();
File file;
public ClientFrame() {
initComponents();
jT = jTextArea1;
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
//send message
try {
String str1 = jTextField1.getText();
String o = jT.getText() + "\n" + " Client ->" + str1;
jT.setText(o);
dos1.writeUTF(str1);
} catch (Exception ex) {
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
//open file chooser
fc.showOpenDialog(this);
file = fc.getSelectedFile();
jTextField3.setText(file.getAbsolutePath());
}
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
//send file
try {
String st = jT.getText() + "\n" + " Client -> " + "Sending a file";
jT.setText(st);
String str1 = "Client Sending a file,Press 'REC File' ";
String st1 = "\n" + " Client ->" + str1;
dos1.writeUTF(st1);
} catch (Exception e) {
}
long length = file.length();
byte[] bytes = new byte[65536];//65536 is max, i think
InputStream in;
try {
in = new FileInputStream(file);
OutputStream out = s.getOutputStream();
int count;
while ((count = in.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
out.close();
in.close();
s_r_m();
} catch (Exception ex) {
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ClientFrame().setVisible(true);
}
});
try {
s = new Socket("localhost", 3000);
} catch (Exception e) {
}
s_r_m();
}
public static void s_r_m() {
System.out.println("call srm");
try {
dis = new DataInputStream(s.getInputStream());
dos1 = new DataOutputStream(s.getOutputStream());
while (true) {
String str = (String) dis.readUTF();
String out = jT.getText() + "\n" + " Server ->" + str;
jT.setText(out);
}
} catch (Exception ex) {
}
}
}
Server Side :
import java.io.*;
import java.net.*;
import javax.swing.JFileChooser;
public class ServerFrame extends javax.swing.JFrame {
static ServerSocket ss;
static Socket s;
static DataInputStream dis;
static DataOutputStream dos1;
static javax.swing.JTextArea jT;
static JFileChooser fc = new JFileChooser();
File file;
public ServerFrame() {
initComponents();
jT = jTextArea1;
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
//send message
try {
String str1 = jTextField1.getText();
String out = jT.getText() + "\n" + " Server ->" + str1;
jT.setText(out);
dos1.writeUTF(str1);
} catch (Exception ex) {
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
//open file chooser
fc.showOpenDialog(this);
file = fc.getSelectedFile();
jTextField3.setText(file.getAbsolutePath());
}
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
//rec file
InputStream in = null;
OutputStream out = null;
try {
in = s.getInputStream();
out = new FileOutputStream("F:\\yoMama.exe");
int count;
byte[] buffer = new byte[65536];
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
}
String o = jT.getText() + "\n" + " Client ->" + " File received";
jT.setText(o);
out.close();
in.close();
s_r_m();
} catch (Exception ex) {
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ServerFrame().setVisible(true);
}
});
try {
ss = new ServerSocket(3000);
s = ss.accept();//will accept connection from client,waiting state untill client connects
s_r_m();
} catch (Exception e) {
}
}
public static void s_r_m() {
System.out.println("call srm");
try {
dis = new DataInputStream(s.getInputStream());
dos1 = new DataOutputStream(s.getOutputStream());
while (true) {
String str = dis.readUTF();
String out = jT.getText() + "\n" + " Client ->" + str;
jT.setText(out);
}
} catch (Exception ex) {
}
}
}

The problem is in the s_r_m() function. In while loop first statement is String str = dis.readUTF(); So here both Client and Server will wait for the reply from the other side first which will end up in a Deadlock. So Any of them won't be able to send any data till the receive from the other side.
So there you need to change code accordingly. I have implemented a code to solve this problem which takes input from Key-Board(STDIN).
DataInputStream dis=new DataInputStream(sckt.getInputStream());
DataInputStream dis1=new DataInputStream(System.in);
DataOutputStream dos=new DataOutputStream(sckt.getOutputStream());
String str="";
while(true)
{
while(dis.available()>0) //If input is available from the other side.
{
String out = jT.getText() + "\n" + " Client ->" + dis.readUTF();
jT.setText(out);
}
while(dis1.available()>0) //If input is available from STDIN to send it to the other side.
{
str=sc.nextLine();
dos.writeUTF(str);
dos.flush();
}
}
Here you can change code of taking input from STDIN to Text-Field you have in your application. So Whenever a user press Send Button , It will send the message to the other side.

Related

Java SocketChannel not receiving incoming data properly

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.

Taking runable class and making it into it's own thread

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();

Error when compiling Java Networking App

So I'm doing this app for a coursework project and I am getting this error when I try to communicate with server:
java.io.StreamCorruptedException: invalid stream header: 43686F6F
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:806)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299)
at Client.ChatClient.<init>(ChatClient.java:31)
at Client.ChatClient.main(ChatClient.java:102)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Here is my Server Code:
public class ChatServer implements Observer {
private ServerSocket serverSocket = null;
private ArrayList<ClientHandler> clients = null;
private Executor service = Executors.newFixedThreadPool(10);
public ChatServer( int port ) {
try {
serverSocket = new ServerSocket( port );
}
catch (IOException e) {
e.printStackTrace();
}
clients = new ArrayList<ClientHandler>();
Thread t = new Thread( new ServerLoop() );
t.start();
}
public void tellEveryone( String message ) {
Iterator it = clients.iterator();
while ( it.hasNext() ) {
System.out.println( 1 );
ClientHandler client = (ClientHandler) it.next();
client.send(message);
}
System.out.println( message );
}
#Override
public void update(Observable o, Object arg) {
System.out.println("from server - updateMethod : " + arg );
}
public class ServerLoop implements Runnable {
public void run() {
try {
while (true) {
Socket clientSocket = serverSocket.accept();
ClientHandler c = new ClientHandler(clientSocket);
clients.add(c);
c.addObserver(ChatServer.this);
service.execute(c);
tellEveryone("new client");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main( String[] args ) {
ChatServer s = new ChatServer( 5000 );
}
}
This is my Client Handler (main part):
public class ClientHandler extends Observable implements Runnable {
private Scanner reader = null;
private PrintWriter writer = null;
private String path = "../";
private Socket client;
private BufferedOutputStream bufferedOutputStream;
private boolean isConnected = false;
private ObjectOutputStream outputStream = null;
private String sourceDirectory = "/home/csunix/sc16hsm/IdeaProjects/ServerClient/src/Server/folder1";
private String destinationDirectory = "/home/csunix/sc16hsm/IdeaProjects/ServerClient/src/Client/Downloads/";
private int fileCount = 0;
private FileEvent fileEvent = null;
public ClientHandler( Socket client ) {
try {
this.client=client;
reader = new Scanner( client.getInputStream() );
writer = new PrintWriter( client.getOutputStream(), true );
bufferedOutputStream = new BufferedOutputStream(client.getOutputStream());
}
catch (IOException e) {
e.printStackTrace();
}
}
public void locateFiles() {
File srcDir = new File(sourceDirectory);
if (!srcDir.isDirectory()) {
System.out.println("Source directory is not valid ..Exiting the client");
System.exit(0);
}
File[] files = srcDir.listFiles();
fileCount = files.length;
if (fileCount == 0) {
System.out.println("Empty directory ..Exiting the client");
System.exit(0);
}
for (int i = 0; i < fileCount; i++) {
System.out.println("Sending " + files[i].getAbsolutePath());
sendFile(files[i].getAbsolutePath(), fileCount - i - 1);
System.out.println(files[i].getAbsolutePath());
}
}
public void sendFile(String fileName, int index) {
fileEvent = new FileEvent();
fileEvent.setDestinationDirectory(destinationDirectory);
fileEvent.setSourceDirectory(sourceDirectory);
File file = new File(fileName);
fileEvent.setFilename(file.getName());
fileEvent.setRemainder(index);
DataInputStream diStream = null;
try {
diStream = new DataInputStream(new FileInputStream(file));
long len = (int) file.length();
byte[] fileBytes = new byte[(int) len];
int read = 0; int numRead = 0;
while (read < fileBytes.length && (numRead = diStream.read(fileBytes, read, fileBytes.length - read)) >= 0) {
read = read + numRead;
}
fileEvent.setFileData(fileBytes);
fileEvent.setStatus("Success");
} catch (Exception e) {
e.printStackTrace();
fileEvent.setStatus("Error");
}
try {
outputStream.writeObject(fileEvent);
} catch (IOException e) {
e.printStackTrace();
}
}
public void listFolders(){
File file = new File("../");
String[] directories = file.list(new FilenameFilter() {
#Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
});
send(Arrays.toString(directories));
}
public void listAll(String fileName){
File folder = new File(path + "/" + fileName);
path = folder.getPath();
System.out.println(path);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
writer.println("File: " + listOfFiles[i].getName());
} else if (listOfFiles[i].isDirectory()) {
writer.println("Directory: " + listOfFiles[i].getName());
}
}
}
public void send( String message ) {
writer.println( message );
}
public void run() {
String message;
writer.println("Choose a file");
listAll("");
while ((message = reader.nextLine()) != null) {
writer.println("Choose a file");
listAll(message);
setChanged();
notifyObservers( message );
if(message.equals("download")) {
System.out.println("MESSAGE FROM CLIENT: " + message);
writer.println("ready");
locateFiles();
}
}
}
}
This is my Client code:
public class ChatClient {
private Scanner socketIn = null;
private PrintWriter socketOut = null;
private Scanner keyboardIn = null;
private Socket socket = null;
private ObjectInputStream inputStream = null;
private FileEvent fileEvent;
private File dstFile = null;
private FileOutputStream fileOutputStream = null;
public ChatClient( String host, int port ) {
try {
Socket socket = new Socket( host, port );
socketIn = new Scanner( socket.getInputStream() );
socketOut = new PrintWriter( socket.getOutputStream(), true );
keyboardIn = new Scanner( System.in );
inputStream = new ObjectInputStream(socket.getInputStream());
}
catch( IOException e ) {
e.printStackTrace();
}
}
public void downloadFiles() {
while (socket.isConnected()) {
try {
fileEvent = (FileEvent) inputStream.readObject();
if (fileEvent.getStatus().equalsIgnoreCase("Error")) {
System.out.println("Error occurred ..with file" + fileEvent.getFilename() + "at sending end ..");
}
String outputFile = fileEvent.getDestinationDirectory() + fileEvent.getFilename();
if (!new File(fileEvent.getDestinationDirectory()).exists()) {
new File(fileEvent.getDestinationDirectory()).mkdirs();
}
dstFile = new File(outputFile);
fileOutputStream = new FileOutputStream(dstFile);
fileOutputStream.write(fileEvent.getFileData());
fileOutputStream.flush();
fileOutputStream.close();
System.out.println("Output file : " + outputFile + " is successfully saved ");
if (fileEvent.getRemainder() == 0) {
System.out.println("Whole directory is copied...So system is going to exit");
System.exit(0);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
private void talktoServer() {
String message;
Thread readerThread = new Thread( new IncomingReader() );
readerThread.start();
while ((message = keyboardIn.nextLine()) != null) {
System.out.println("client typed: " + message);
socketOut.println( message );
}
}
private class IncomingReader implements Runnable {
public void run() {
String message;
while ((message = socketIn.nextLine()) != null) {
System.out.println("client read: " + message);
if(message.equals("ready")) {
downloadFiles();
}
}
}
}
public static void main( String[] args ) {
ChatClient c = new ChatClient( "127.0.0.1", 5000 );
c.talktoServer();
}
}
Any help at all would be greatly appreciated!

How to add a Text into a List from another Client or Server?

I am trying to program my own chat but I can't get the text from one client to the next. I have the chat as a list but I can't add it. If you know how to solve it or have a idea that might work, I would love to hear it.
public class SendAction implements ActionListener {
private JButton sendButton;
private JButton sendButtonServer;
private JTextField text;
private JLabel label;
static ArrayList<String> textList = new ArrayList<String>();
static ArrayList<String> textListServer = new ArrayList<String>();
private String chatText;
public SendAction(JButton sendButton) {
this.sendButton = sendButton;
this.sendButtonServer = sendButtonServer;
}
public SendAction(JTextField text) {
this.text = text;
}
public SendAction(JLabel label) {
this.label = label;
}
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
if (e.getSource() == P2PChatClient.sendButton) {
if (P2PChatClient.text.getText().equals("")) {
} else {
textList.add("Client: " + P2PChatClient.text.getText());
System.out.println("Eingegebene ArrayList Elements: "
+ textList);
chatText = String.join(" | ", textList);
P2PChatClient.label.setText(chatText);
P2PChatClient.text.setText(null);
}
}
if (e.getSource() == P2PChatServer.sendButtonServer) {
if (P2PChatServer.textServer.getText().equals("")) {
} else {
textListServer.add("Server: "
+ P2PChatServer.textServer.getText());
System.out.println("Eingegebene ArrayList Elements: "
+ textListServer);
chatText = String.join(" | ", textListServer);
P2PChatServer.labelServer.setText(chatText);
P2PChatServer.textServer.setText(null);
}
}
}
}
another Class:
public class ChatServerSocket extends Thread {
private int port;
private P2PChatServer serverGUI;
private DataInputStream inStream;
private DataOutputStream outStream;
public ChatServerSocket(int port, P2PChatServer serverGUI) {
this.port = port;
this.serverGUI = serverGUI;
}
public void run() {
ServerSocket server = null;
try {
server = new ServerSocket(port);
} catch (Exception e) {
System.out.println("Fehler: " + e.toString());
}
Socket client;
while (true) {
try {
client = server.accept();
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();
inStream = new DataInputStream(in);
outStream = new DataOutputStream(out);
while (true) {
String utf = inStream.readUTF();
// File file = new File(utf);
// if (file.isFile()) {
// file.delete();
// }
SendAction.textListServer.add(utf);
// serverGUI.setMessage(utf);
}
} catch (IOException ioe) {
System.out.println("Server Fehler: " + ioe.toString());
}
}
}
public void sendText(String message) {
// P2PChatServer.send();
try {
if (message != null) {
outStream.writeUTF(message);
}
} catch (IOException ioe) {
System.out.println("Fehler beim senden im Server: "
+ ioe.toString());
} catch (NullPointerException npe) {
System.out.println("Fehler beim senden im Client: "
+ npe.toString());
}
}
}
and another:
public class ChatClientSocket extends Thread {
private String ip;
private int port;
private P2PChatClient client;
private DataInputStream inStream;
private DataOutputStream outStream;
public ChatClientSocket(String ip, int port, P2PChatClient client) {
this.port = port;
this.ip = ip;
this.client = client;
}
public void run() {
try {
Socket clientSocket = new Socket(ip, port);
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
inStream = new DataInputStream(in);
outStream = new DataOutputStream(out);
while (true) {
String utf = inStream.readUTF();
SendAction.textList.add(utf);
// client.setMessage(utf);
}
} catch (UnknownHostException uhe) {
System.out.println("Client Fehler: " + uhe.toString());
} catch (IOException ioe) {
System.out.println("Client Fehler: " + ioe.toString());
}
}
public void sendText(String message) {
try {
if (message != null) {
outStream.writeUTF(message);
}
} catch (IOException ioe) {
System.out.println("Fehler beim senden im Client: "
+ ioe.toString());
} catch (NullPointerException npe) {
System.out.println("Fehler beim senden im Client: "
+ npe.toString());
}
}
}
I used a textarea.
With setEditable you cant edit it and scrollArea make it scrollable u know.
textArea.setEditable(false);
scrollArea = new JScrollPane(textArea);

Swing problem!(problem in showing a frame)

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.

Categories