Hello I am having trouble with getting both the server and the clients connecting to each other when they are not on the same network. Please could you have a look at the code and see what I need to do to fix this issue.
I am new at Java and with the whole networking side of things so any help would be appreciated.
Server
>!
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
public class ChatServer {
private static final int PORT = 9001;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
private static class Handler extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
// Create character streams for the socket.
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Request a name from this client. Keep requesting until
// a name is submitted that is not already used. Note that
// checking for the existence of a name and adding the name
// must be done while locking the set of names.
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
break;
}
}
}
// Now that a successful name has been chosen, add the
// socket's print writer to the set of all writers so
// this client can receive broadcast messages.
out.println("NAMEACCEPTED");
writers.add(out);
// Accept messages from this client and broadcast them.
// Ignore other clients that cannot be broadcasted to.
while (true) {
String input = in.readLine();
if (input == null) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (IOException e) {
System.out.println(e);
} finally {
// This client is going down! Remove its name and its print
// writer from the sets, and close its socket.
if (name != null) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
Client
>!
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ChatClient {
BufferedReader in;
PrintWriter out;
JFrame frame = new JFrame("Messager");
JTextField textField = new JTextField(40);
JTextArea messageArea = new JTextArea(8, 40);
public ChatClient() {
// Layout GUI
textField.setEditable(false);
messageArea.setEditable(false);
frame.getContentPane().add(textField, "North");
frame.getContentPane().add(new JScrollPane(messageArea), "Center");
frame.pack();
// Add Listeners
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
out.println(textField.getText());
textField.setText("");
}
});
}
/**
* Prompt for and return the address of the server.
*/
private String getServerAddress() {
return JOptionPane.showInputDialog(
frame,
"Enter IP Address of the Server:",
"Welcome to the Messager",
JOptionPane.QUESTION_MESSAGE);
}
/**
* Prompt for and return the desired screen name.
*/
private String getName() {
return JOptionPane.showInputDialog(
frame,
"Choose a screen name:",
"Screen name selection",
JOptionPane.PLAIN_MESSAGE);
}
/**
* Connects to the server then enters the processing loop.
*/
private void run() throws IOException {
// Make connection and initialize streams
String serverAddress = getServerAddress();
Socket socket = new Socket("86.190.97.107", 9001);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Process all messages from server, according to the protocol.
while (true) {
String line = in.readLine();
if (line.startsWith("SUBMITNAME")) {
out.println(getName());
} else if (line.startsWith("NAMEACCEPTED")) {
textField.setEditable(true);
} else if (line.startsWith("MESSAGE")) {
messageArea.append(line.substring(8) + "\n");
}
}
}
/**
* Runs the client as an application with a closeable frame.
*/
public static void main(String[] args) throws Exception {
ChatClient client = new ChatClient();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setVisible(true);
client.run();
}
}
Thanks for all of your answers i found out that the server needed to be hosted on a separate computer for the external IP to work.
Related
I have a server client application working just how I want it locally. I need to get the server online so the client program can be used from different computers. Not sure how to do this. I have my own website that I thought I could just put the Server on in the background.
Is this possible or am I just looking at this the wrong way.
Server.java
package core;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
public class Server {
public static void main(String[] args) throws IOException {
ArrayList<ClientHandler> clients = new ArrayList<>();
ServerSocket serverSocket = null;
int clientNum = 1; // keeps track of how many clients were created
// 1. CREATE A NEW SERVERSOCKET
try {
serverSocket = new ServerSocket(4444); // provide MYSERVICE at port
// 4444
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
System.exit(-1);
}
// 2. LOOP FOREVER - SERVER IS ALWAYS WAITING TO PROVIDE SERVICE!
while (true) {
Socket clientSocket = null;
try {
// 2.1 WAIT FOR CLIENT TO TRY TO CONNECT TO SERVER
System.out.println("Waiting for client " + clientNum + " to connect!");
clientSocket = serverSocket.accept();
clientNum++;
ClientHandler c = new ClientHandler(clientSocket, clients);
clients.add(c);
// 2.2 SPAWN A THREAD TO HANDLE CLIENT REQUEST
Thread t = new Thread(c);
t.start();
} catch (IOException e) {
System.out.println("Accept failed: 4444");
System.exit(-1);
}
// 2.3 GO BACK TO WAITING FOR OTHER CLIENTS
// (While the thread that was created handles the connected client's
// request)
} // end while loop
} // end of main method
} // end of class MyServer
class ClientHandler implements Runnable {
Socket s; // this is socket on the server side that connects to the CLIENT
ArrayList<ClientHandler> others;
Scanner in;
PrintWriter out;
ClientHandler(Socket s, ArrayList<ClientHandler> others) throws IOException {
this.s = s;
this.others = others;
in = new Scanner(s.getInputStream());
out = new PrintWriter(s.getOutputStream());
}
/*
* (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run() {
// 1. USE THE SOCKET TO READ WHAT THE CLIENT IS SENDING
while (true) {
String clientMessage = in.nextLine();
// System.out.println(clientMessage);
new Thread(new Runnable() {
#Override
public void run() {
try (PrintWriter fileWriter = new PrintWriter(new FileOutputStream(new File("chat.txt"), true));) {
fileWriter.println(clientMessage);
fileWriter.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println(others.size());
for (ClientHandler c : others) {
// System.out.println(c.toString());
c.sendMessage(clientMessage);
}
}
}).start();
}
}
private void sendMessage(String str) {
out.println(str);
out.flush();
}
} // end of class ClientHandler
ClientSide.java
package core;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.BoxLayout;
import javax.swing.JTextArea;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
public class ClientSide extends JFrame {
private JPanel contentPane;
private JTextField textField;
private String name;
private JTextArea textArea;
private Thread serverListener;
private Socket socket;
private Scanner in;
private PrintWriter out;
// /**
// * Launch the application.
// */
// public static void main(String[] args) {
// EventQueue.invokeLater(new Runnable() {
// public void run() {
// try {
// ClientSide frame = new ClientSide();
// frame.setVisible(true);
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// });
// }
/**
* Create the frame.
*
* #throws IOException
*/
public ClientSide(String myName) {
try {
socket = new Socket("localhost", 4444);
in = new Scanner(socket.getInputStream());
out = new PrintWriter(socket.getOutputStream());
} catch (IOException e1) {
e1.printStackTrace();
}
serverListener = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
String clientMessage = in.nextLine();
try {
System.out.println("Receiving before dec: " + clientMessage);
clientMessage = Crypto.decrypt(clientMessage, "key");
System.out.println("Receiving after dec: " + clientMessage);
addLine(clientMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
serverListener.start();
name = myName;
setTitle("Client Side");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
JPanel topPanel = new JPanel();
FlowLayout flowLayout = (FlowLayout) topPanel.getLayout();
flowLayout.setAlignment(FlowLayout.LEFT);
contentPane.add(topPanel);
textArea = new JTextArea();
textArea.setEditable(false);
textArea.setColumns(20);
textArea.setRows(7);
topPanel.add(textArea);
JPanel bottomPanel = new JPanel();
contentPane.add(bottomPanel);
bottomPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
JLabel lblMessage = new JLabel("Message");
bottomPanel.add(lblMessage);
textField = new JTextField();
bottomPanel.add(textField);
textField.setColumns(10);
JButton btnSend = new JButton("Send");
btnSend.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// send string/message to server
String clientMessage;
try {
clientMessage = Crypto.encrypt(name + ": > " + textField.getText(), "key");
System.out.println("Sending: " + clientMessage);
out.println(clientMessage);
out.flush();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
bottomPanel.add(btnSend);
}
public void addLine(String text) {
textArea.setText(textArea.getText() + text + "\n");
}
}
Provided your ClientSide class connects with your server applicztion on port 4444, you can do the following:
Package your client as jar file and run on each computer you want to distribute it to.
Ensure, each of those computers have JRE installed.
3 Package your Server module as jar file
You should own your server or have admin right. So you can install Java if not there.
Depending on OS, SSH skill might be required
Ensure PORT 4444 is enabled on your host server. firewall
Get the public IP address of your server and use it in your ClideSide code.
I'm trying to write a poker server and client program, I create the game in the server class and my client class takes the output and displays them. However, when ever i do this, there seem to be two game objects created, the first player gets the input that is consistent with the object that is shown in the console, the second player always displays cards that are not shown in the sysout method, and I can not seem to find where I created the second game object.
server class:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashSet;
public class PokerServer {
/**
* The port that the server listens on.
*/
private static final int PORT = 9050;
// keeps track of all the names
private static ArrayList<String> names = new ArrayList<String>();
// broadcast messages
private static ArrayList<PrintWriter> writers = new ArrayList<PrintWriter>();
private boolean bothPlayersConnected = false;
/**
* The appplication main method, which just listens on a port and spawns
* handler threads.
*/
public static void main(String[] args) throws Exception {
System.out.println("The poker server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new GameThread(listener.accept()).start();
}
} finally {
listener.close();
}
}
private static class GameThread extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private Game game;
public GameThread(Socket socket) {
this.socket = socket;
}
/**
* Services this thread's client by repeatedly requesting a screen name
* until a unique one has been submitted, then acknowledges the name and
* registers the output stream for the client in a global set, then
* repeatedly gets inputs and broadcasts them.
*/
public void run() {
try {
System.out.println("get to this part");
// Create character streams for the socket.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// get the name of the player
out.println("SUBMITNAME");
name = in.readLine();
names.add(name);
while(names.size()<2){
out.println("MESSAGE waiting for opponent to connect");
}
// Now that a successful name has been chosen, add the
// socket's print writer to the set of all writers so
// this client can receive broadcast messages.
// out.println("NAMEACCEPTED");
// writers.add(out);
game = new Game(names.get(0), names.get(1), 1000);
game.dealToPlayers();
out.println(names.get(0) + game.getPlayer1().getHand()[0].transferStr());
out.println(names.get(0) + game.getPlayer1().getHand()[1].transferStr());
out.println(names.get(1) + game.getPlayer2().getHand()[0].transferStr());
out.println(names.get(1) + game.getPlayer2().getHand()[1].transferStr());
// Accept messages from this client and broadcast them.
// Ignore other clients that cannot be broadcasted to.
while (true) {
String input = in.readLine();
if (input == null) {
return;
} else if (input.startsWith(names.get(0))) {
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (IOException e) {
System.out.println(e);
} finally {
// This client is going down! Remove its name and its print
// writer from the sets, and close its socket.
if (name != null) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
Client class
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class PokerClient {
BufferedReader in;
PrintWriter out;
String playerName = "Poker";
JFrame frame = new JFrame(playerName);
JPanel playerHandPanel, controlPanel, bottomPanel, topPanel, messageBoard;
JButton check, fold;
JTextField textField = new JTextField(10);
JLabel firstLine = new JLabel("");
String serverAddress = "localhost";
Card playerHand1, playerHand2;
public PokerClient() {
// Layout GUI
frame.setSize(1100, 700);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
playerHandPanel = new JPanel(new GridLayout(1, 0));
playerHandPanel.setPreferredSize(new Dimension(600, 300));
playerHandPanel.setVisible(true);
topPanel = new JPanel(new GridLayout(1, 0));
topPanel.setPreferredSize(new Dimension(900, 300));
topPanel.setVisible(true);
messageBoard = new JPanel(new GridLayout(0, 1));
messageBoard.add(firstLine);
controlPanel = new JPanel();
controlPanel.setPreferredSize(new Dimension(600, 40));
controlPanel.setVisible(true);
topPanel.add(messageBoard);
check = new JButton("Check");
check.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
out.println(playerName+"CHECK");
}
});
fold = new JButton("fold");
fold.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
out.println(playerName+"FOLD");
}
});
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(isInt(textField.getText())){
out.println(textField.getText());
textField.setText("");
} else{
JFrame frame = new JFrame("Not a number");
frame.setSize(600, 70);
frame.setLocation(400, 250);
frame.setResizable(false);
JLabel label = new JLabel("You must enter a number in order to raise");
frame.add(label);
frame.setVisible(true);
frame.toFront();
frame.repaint();
textField.setText("");
}
}
});
controlPanel.add(check);
controlPanel.add(fold);
controlPanel.add(new JLabel(" Raise:"));
controlPanel.add(textField);
bottomPanel = new JPanel();
bottomPanel.add(controlPanel, BorderLayout.SOUTH);
bottomPanel.add(playerHandPanel, BorderLayout.NORTH);
frame.add(topPanel, BorderLayout.NORTH);
frame.add(bottomPanel, BorderLayout.SOUTH);
//frame.add(firstLine, "SOUTH");
frame.setVisible(true);
}
private static boolean isInt(String s)
{
try
{ int i = Integer.parseInt(s); return true; }
catch(NumberFormatException er)
{ return false; }
}
/**
* Prompt for and return the desired screen name.
*/
private String getName() {
return JOptionPane.showInputDialog(
frame,
"Choose a screen name:",
"Screen name selection",
JOptionPane.PLAIN_MESSAGE);
}
private Card constructCard(String line){
int seperator = line.indexOf('/');
int cardNum = Integer.parseInt(line.substring(0, seperator));
Card card;
if(line.substring(seperator+1).startsWith("S")){
card = new Card(cardNum, Suit.SPADE);
} else if(line.substring(seperator+1).startsWith("C")){
card = new Card(cardNum, Suit.CLUB);
} else if(line.substring(seperator+1).startsWith("D")){
card = new Card(cardNum, Suit.DIAMOND);
} else{
card = new Card(cardNum, Suit.HEART);
}
System.out.println(card.toString());
return card;
}
/**
* Connects to the server then enters the processing loop.
*/
private void run() throws IOException {
Socket socket = new Socket(serverAddress, 9050);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Process all messages from server, according to the protocol.
while (true) {
String line = in.readLine();
System.out.println(line);
if (line.startsWith("SUBMITNAME")) {
String name = getName();
playerName = name;
out.println(name);
frame.setTitle(playerName);
} else if (line.startsWith(playerName)) {
playerHandPanel.add(new CardComponent(constructCard(line.substring(playerName.length()))));
playerHandPanel.revalidate();
playerHandPanel.repaint();
} else if(line.startsWith("CARD")){
topPanel.add(new CardComponent(constructCard(line.substring(4))));
topPanel.revalidate();
topPanel.repaint();
} else if(line.startsWith("MESSAGE")){
firstLine.setText(line.substring(7));
}
}
}
public static void main(String[] args) throws Exception {
PokerClient client = new PokerClient();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setVisible(true);
client.run();
}
}
Im making a chat program.
i got the client to server connection working but i cant get the server to send to all sockets. Since Im using ObjectOutputStream i cant use PrintWriter which was the way I did it before, Heres my code thanks for the help
Server
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
public Server clients[] = new Server[50];
public static String user;
private static final int PORT = 4000;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<>();
public static void main(String[] args) throws Exception{
System.out.println("The chatroom is running...");
ServerSocket listener = new ServerSocket(PORT);
try{
while(true){
new Handler(listener.accept()).start();
}
}
catch(Exception e){
System.err.println(e);
}
finally{
listener.close();
}
}
private static class Handler extends Thread{
private String name;
private Socket socket;
//private BufferedReader in;
//private PrintWriter out;
public ObjectOutputStream out;
public ObjectInputStream in;
public void send(Message msg) throws IOException{
out.writeObject(msg);
out.flush();
}
public void Announce(String type, String sender, String content){
Message msg = new Message(type, sender, content, "All");
}
public Handler(Socket socket){
this.socket = socket;
}
public void run(){
try {
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = (new ObjectInputStream(socket.getInputStream()));
out.writeObject(new Message("SUBMITNAME", "blank", "blank", "blank"));
while(true){
Message msg = (Message) in.readObject();
if(msg.sender == null){
return;
}
if(!names.contains(msg.sender)){
names.add(msg.sender);
System.out.println(names.toString());
System.out.println("The object is " + msg);
}
break;
}
while(true){
Message msg = (Message) in.readObject();
System.out.println(msg);
names.add(msg.sender);
System.out.println(names.toString());
break;
}
//out.writeObject(new Message("MESSAGE", "Server", "Welcome To the ChatRoom", "c"));
while(true){
Message msg = (Message) in.readObject();
if(msg.type.equals("MESSAGE")){
out.writeObject(new Message("MESSAGE", msg.sender, msg.content, "all"));
System.out.println(msg.sender + ": " + msg.content);
}
}
}
catch (Exception e) {
System.err.println(e);
}
finally{
try{
socket.close();
System.out.println("Socket has closed");
}
catch(IOException e){
System.err.println("Problem closing socket!");
}
}
}
}
}
Client
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.DefaultCaret;
import static javax.swing.text.DefaultCaret.ALWAYS_UPDATE;
public class Client implements Serializable{
//private BufferedReader in;
//private PrintWriter out;
ObjectOutputStream out;
ObjectInputStream in;
String name;
JFrame frame = new JFrame("Client Box");
JTextField textField = new JTextField(40);
JTextArea messageArea = new JTextArea(8,40);
JScrollPane scroll = new JScrollPane(messageArea);
ArrayList<String> list = new ArrayList();
public Client(){
textField.setEditable(false);
messageArea.setEditable(false);
messageArea.setWrapStyleWord(true);
messageArea.setLineWrap(true);
DefaultCaret caret = (DefaultCaret) messageArea.getCaret();
caret.setUpdatePolicy(ALWAYS_UPDATE);
//frame.setLayout(new BorderLayout());
frame.getContentPane().add(textField, BorderLayout.SOUTH);
frame.getContentPane().add(scroll, BorderLayout.CENTER);
frame.pack();
textField.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
//Message msg = new Message("MESSAGE", name, textField.getText(), "all");
//out.writeObject(msg);
sendAll("MESSAGE", name, textField.getText());
textField.setText("");
}catch(IOException ex){System.err.println(ex.printStackTrace()};
}
});
}
public void sendAll(String type, String sender, String content) throws IOException{
Message msg = (new Message(type, sender, content, "all"));
out.writeObject(msg);
out.flush();
}
private String getName(){
return JOptionPane.showInputDialog(frame, "Your Screen Name?", "Please Enter Screen Name: "
, JOptionPane.PLAIN_MESSAGE);
}
private String getMessage(){
return JOptionPane.showInputDialog(frame, "Your message?", "Please Enter Screen Name: "
, JOptionPane.PLAIN_MESSAGE);
}
private void run() throws IOException, ClassNotFoundException{
//String address = getServerAddress();
Socket socket = new Socket("localhost", 4000);
in = (new ObjectInputStream(socket.getInputStream()));
out = new ObjectOutputStream(socket.getOutputStream());
Message temp = (Message) in.readObject();
if(temp.type.equals("SUBMITNAME")){
textField.setEditable(true);
name = getName();
sendAll(name, "a", " b");
}
while(true){
Message msg = (Message) in.readObject();
messageArea.append(msg.sender + ": " + msg.content + "\n");
}
}
public static void main(String[] args) throws ClassNotFoundException{
Client client = new Client();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setLocationRelativeTo(null);
client.frame.setVisible(true);
try {
try {
client.run();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I didn't realize until now that my disconnect button on my program was failing. If I have 3 clients up, and any of them click disconnect, then only the last client gets disconnected. How do I select which instance I need to close? If out of the 3 users I want to remove the first one..
server:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Server {
private Set<Socket> sockets = new HashSet<Socket>();
private Set<String> names = new HashSet<String>();
private Socket sock;
private static int port;
private Calendar cal = Calendar.getInstance();
private SimpleDateFormat date = new SimpleDateFormat("dd/mm/yyyy hh:mm:ss");
public Server(int input) {
port = input;
}
public static void main(String[] args) {
/*
* user defines port number, server initialized
*/
System.out.println("enter a port");
Scanner input = new Scanner(System.in);
port = input.nextInt();
new Server(port).go();
input.close();
}
public void go() {
try {
/*
* wait for connections, add connections to Set, setup streams per
* connection in new threads
*/
System.out.println("waiting for connetion");
#SuppressWarnings("resource")
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
sock = serverSocket.accept();
sockets.add(sock);
Thread t = new Thread(new ClientHandler(sock));
t.start();
System.out.println("connected: " + sock.getInetAddress());
}
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("server setup failed");
}
}
class ClientHandler implements Runnable {
/*
* client handler sets up streams
*/
private BufferedReader in;
private PrintWriter out;
private String name;
public ClientHandler(Socket sock) {
try {
in = new BufferedReader(new InputStreamReader(
sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
System.out.println("stream setup failed");
}
}
#Override
public void run() {
/*
* First check if user exists, if true than close connection and
* warn user about name. Then relay message to all clients, if user
* DC's than remove the socket from the Set
*/
String message;
try {
name = in.readLine();
if (names.contains(name)) {
System.out.println("duplicate name detected, removing..");
out.println("choose new name and reconnect: "
+ sock.getInetAddress());
sock.close();
sockets.remove(sock);
} else {
names.add(name);
System.out.println("Users active: " + names);
shout("user: " + name + " connected!" + " from "
+ sock.getInetAddress());
}
while ((message = in.readLine()) != null) {
/*
* call method which checks if user tries to enter a command
* such as /laugh or /roll, otherwise relay the message to
* all clients
*/
swich(message);
}
} catch (IOException ex) {
System.out.println("user disconnected: " + name + " "
+ sock.getInetAddress());
shout("user disconnected: " + name + " "
+ sock.getInetAddress());
names.remove(name);
remove(sock);
}
}
public synchronized void shout(String message) {
// send message to all clients in Set
for (Socket sock : sockets) {
try {
PrintWriter writer = new PrintWriter(
sock.getOutputStream(), true);
writer.println(date.format(cal.getTime()) + " " + message
+ "\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void swich(String message) throws IOException {
// check if user calls a chat command
// otherwise shout message to all clients
switch (message) {
case "/disconnect":
out.println("disconnected");
remove(sock);
break;
case "/laugh":
String[] laughs = { "HahHA!", "HAHAAH!!!!", "haaaaa!!!",
"hohohoohohahhaa!!!", "huehuehue!" };
shout(name + " " + laughs[(int) (Math.random() * 5)]);
break;
case "/roll":
shout(name + " rolls "
+ Integer.toString((int) ((Math.random() * 6) + 1)));
break;
case "kirby!":
shout("(>'-')> <('-'<) ^(' - ')^ <('-'<) (>'-')>");
break;
default:
shout(message);
System.out.println("client says : "
+ date.format(cal.getTime()) + message);
}
}
}
public void remove(Socket soc) {
try {
soc.close();
sockets.remove(soc);
} catch (IOException e) {
e.printStackTrace();
}
}
}
client:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Client {
private JTextArea tArea;
private JTextField tField;
private JTextField portText;
private JTextField hostText;
private BufferedReader in;
private Socket sock;
private static PrintWriter out;
private static String name;
private String host;
private String port;
public static void main(String[] args) {
System.out.println("Enter username");
Scanner input = new Scanner(System.in);
name = input.nextLine();
input.close();
new Client().go();
}
public void go() {
/*
* build gui
*/
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("hakobChat");
JPanel topPanel = new JPanel();
JLabel portLabel = new JLabel("port");
JLabel hostLabel = new JLabel("host");
portText = new JTextField(6);
hostText = new JTextField(12);
JButton connect = new JButton("connect");
connect.addActionListener(new connectListener());
JButton disconnect = new JButton("disconnect");
disconnect.addActionListener(new disconnectListener());
tField = new JTextField(30);
tField.addActionListener(new sendListener());
tArea = new JTextArea(30, 50);
tArea.setEditable(false);
tArea.setLineWrap(true);
JScrollPane tScroll = new JScrollPane(tArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JButton button = new JButton("send");
button.addActionListener(new sendListener());
topPanel.add(hostLabel);
topPanel.add(hostText);
topPanel.add(portLabel);
topPanel.add(portText);
topPanel.add(connect);
topPanel.add(disconnect);
frame.setSize(300, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(topPanel, BorderLayout.NORTH);
frame.getContentPane().add(tScroll, BorderLayout.CENTER);
frame.getContentPane().add(tField, BorderLayout.SOUTH);
frame.getContentPane().add(button, BorderLayout.EAST);
frame.pack();
}
});
}
public void setupNetwork(String host, int port) {
/*
* setup in and out stream send user name to server to check if
* duplicate start thread for incoming messages
*/
try {
sock = new Socket(host, port);
in = new BufferedReader(
new InputStreamReader(sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream(), true);
out.println(name);
showMessage("Connected!");
showMessage("enter /laugh or /roll or kirby! for some fun!");
Thread t = new Thread(new IncomingReader());
t.start();
} catch (IOException ex) {
ex.printStackTrace();
showMessage("please enter valid network");
}
}
class IncomingReader implements Runnable {
// receive messages from server
public void run() {
try {
String message = null;
while ((message = in.readLine()) != null) {
showMessage(message + "\n");
}
} catch (Exception e) {
e.printStackTrace();
showMessage("choose new name and reconnect please");
}
}
}
public synchronized void sendMessage(String message) {
try {
switch (message) {
case "/laugh":
out.println("/laugh");
break;
case "/roll":
out.println("/roll");
break;
case "kirby!":
out.println("kirby!");
break;
default:
out.println("(" + name + ")" + ": " + message);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("fail send message");
}
}
public void showMessage(final String message) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
tArea.append(message + "\n");
tArea.setCaretPosition(tArea.getDocument().getLength());
// SetCaretPosition forces autos scroll
}
});
}
class sendListener implements ActionListener {
// listens for user to trying to send a message
public void actionPerformed(ActionEvent ev) {
sendMessage(tField.getText());
tField.setText("");
}
}
class disconnectListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
try {
out.println("/disconnect");
} catch (NullPointerException e) {
showMessage("not connected");
}
}
}
class connectListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
host = hostText.getText();
port = portText.getText();
if (!host.equals("") && !port.equals("") && port.matches("[1-9]+")) {
// make sure user enters valid inputs
// before setting up network
setupNetwork(host, Integer.parseInt(port));
} else {
showMessage("enter valid network credentials");
}
}
}
}
Also, how do I avoid this "#SuppressWarnings("resource")". If I don't have this eclipse provided warning than the serverSocket is underlined yellow.
You need to save a the Socket used for the client inside of the ClientHandler.
You can do this by simply adding a
private Socket sock;
inside of ClientHandler, and adding:
this.sock = sock;
inside of its constructor.
Currently you're using the Socket saved in the server, which will always be the socket of the last client that connected, rather than the Socket belonging to the current client.
This is just a scoping problem. The Socket sock member shouldn't be part of the Server class. It should be part of the ClientHandler class. One per client.
I have a problem with readLine() in Java. I have a server and a client. From client I want to send a message to the server. The problem is that first, the client has to insert a text into a JTextField and when presses send then server to read the input from client, but server doesn't wait the input from client but instead reads null. But I read that readLine() is blocked until it has something to read, why it's not happening in this case?
Here I connect to the server and create the JFrame
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.JFrame;
import javax.swing.SwingUtilities;
public class StartingPoint {
private static PrintWriter out;
private static BufferedReader in;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
connectToServer();
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public static void createAndShowGui() throws IOException {
View frame = new View(out, in);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void connectToServer() throws IOException {
String serverAddress = "127.0.0.1";
int PORT = 8100;
Socket clientSocket = null;
out = null;
in = null;
try {
clientSocket = new Socket(serverAddress, PORT);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Could not connect to the server \n" + e);
System.exit(1);
} finally {
if (out != null)
out.close();
if (in != null)
in.close();
if (clientSocket != null)
clientSocket.close();
}
}
}
Here is JFrame implementation:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class View extends JFrame {
private JButton button;
private JTextField field;
private JPanel gui;
public View(final PrintWriter out, final BufferedReader in) throws IOException {
button = new JButton("Send");
field = new JTextField();
gui = new JPanel(new GridLayout(1, 0, 10, 10));
gui.add(button);
gui.add(field);
add(gui);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
out.println(field.getText());
try {
System.out.println(in.readLine());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
Here is the server:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleServer extends Thread {
public static final int PORT = 8100;
private static ServerSocket serverSocket = null;
private Socket clientSocket = null;
public void run() {
String receive, answer;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
receive = in.readLine();
System.out.println("[server]" + receive);
answer = "hello " + receive;
out.println(answer);
out.flush();
} catch (IOException e) {
System.err.println("IO error \n" + e);
} finally {
try {
clientSocket.close();
} catch (IOException e) {
System.err.println("Close socket error \n" + e);
}
}
}
public SimpleServer() throws IOException {
while (true) {
serverSocket = new ServerSocket(PORT);
try {
clientSocket = serverSocket.accept();
new Thread(this).start();
} finally {
serverSocket.close();
}
}
}
public static void main(String[] args) throws IOException {
SimpleServer server = new SimpleServer();
}
}
Your connectToServer() method opens a connection, creates streams and ... then closes them before returning. So of course, the server sees the close straight away, and returns null on the first readLine() call.
I suspect that you may have copied the "close in a finally block" pattern without understanding what it means. So I shall explain:
This is the normal pattern:
InputStream is = null;
try {
is = new FileInputStream(someFile);
// read the stream
} finally {
if (is != null) {
is.close();
}
}
The purpose of the code above is to ensure that the InputStream is always closed. Or more precisely, that it is always closed before the try/finally exits.
This is generally a good thing. But if the purpose of your code is to open some streams that is going to be used after this bit of code completes, then closing the stream here is self defeating.
InputStream is = null;
try {
is = new FileInputStream(someFile);
} finally {
if (is != null) {
is.close();
}
}
// read the stream ... OOOPS! We've already closed it!!
So to take this back to your original code, you need to move the try/finally/close stuff to the run method, something along these lines:
public void run() {
try {
connectToServer();
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null)
out.close();
if (in != null)
in.close();
if (clientSocket != null)
clientSocket.close();
}
}
You should also catch and (probably) ignore IOException that might be thrown by each close() call.
Javadoc for BufferedReader.readLine()
doesn't say anything like that:
Returns:
A String containing the contents of the line, not including
any line-termination characters, or null if the end of the stream has been reached
In your code you are opening a connection in connectToServer() and closing it, so server sees the end of stream