Using JFrame from another class - java

Hi I'm small a little issue trying to append some text to a JTextArea from another class within the same package. Below is the main class that pertains to the JFrame:
public class Client extends JFrame{
//Static variables
private static final String host = "localhost";
private static final int portNumber = 4444;
//Variables
private String userName;
//JFrame Variables
private JPanel contentPanel;
private JTabbedPane panel_Social;
private JPanel jpanel_Social;
private JPanel jpanel_Chat;
private JTextArea textArea_Receive;
private JTextField textField_Send;
private JTextArea textArea_ClientList;
private JButton btn_Enter;
public JTextArea getTextArea_Receive(){
return this.textArea_Receive;
}
//Constructor
private Client(String userName, String host, int portNumber){
this.userName = userName;
this.serverHost = host;
this.serverPort = portNumber;
}
public void main(String args[]){
//Requests user to enter name
String readName = null;
Scanner scan = new Scanner(System.in);
System.out.println("Please enter username");
readName = scan.nextLine();
//Start client
Client client = new Client(readName, host, portNumber);
client.startClient(scan);
}
private void startClient(Scanner scan){
try{
//Create new socket and wait for network communication
Socket socket = new Socket(serverHost, serverPort);
Thread.sleep(1000);
//Create thread and start it
serverThread = new ServerThread(socket, userName);
Thread serverAccessThread = new Thread(serverThread);
serverAccessThread.start();
}
}
}
Below is the serverThread class
public class ServerThread implements Runnable{
private Socket socket;
private String userName;
private boolean isAlived;
private final LinkedList<String> messagesToSend;
private boolean hasMessages = false;
//Constructor
ServerThread(Socket socket, String userName){
this.socket = socket;
this.userName = userName;
messagesToSend = new LinkedList<String>();
}
public void run(){
try{
Client test1 = new Client();
JTextArea test2 = test1.getTextArea_Receive();
String test3 = "Hello World";
test2.append(test3);
} catch (IOException e){
}
}
I included test variables just to easily recreate the issue but whenever the append function is run nothing appears in the text area of the jFrame. In my scenario I'm having the client receive text from a server then append it to the text box.
BTW I'm using the IntelliJ GUI designer for the JFrame. I've only included code needed to recreate the problem. I'm still trying to create MCVE questions so feel free to let me know mistakes I made.

You should pass Client into ServerThread via the constructor. The Client you are instantiating within run() is not the same reference to the Client you created in main(). So your ServerThread class would be something like
ServerThread(Client client, Socket socket, String userName) {
this.client = client;
this.socket = socket;
this.userName = userName;
messagesToSend = new LinkedList<String>();
}
public void run() {
try
{
JTextArea test2 = this.client.getTextArea_Receive();
String test3 = "Hello World";
test2.append(test3);
}
catch (IOException e)
{}
}
Your startClient() method would be updated to something like this
private void startClient(Client client, Scanner scan)
{
try
{
//Create new socket and wait for network communication
Socket socket = new Socket(serverHost, serverPort);
Thread.sleep(1000);
//Create thread and start it
ServerThread serverThread = new ServerThread(client, socket, userName);
serverAccessThread.run();
}
}
All that being said,
I would recommend moving your main() out of Client and into a class that isn't so coupled to the Swing UI code. Something like this:
public class MySwingApplication {
private static final String host = "localhost";
private static final int portNumber = 4444;
public static void main(String[] args) {
// Requests user to enter name
// Start client
}
}
Your Client is then built more like an instance object
public class Client extends JFrame {
public JTextArea getTextArea_Receive(){
// Return the text area
}
// Constructor -- public to allow instantiation from main()
public Client(String userName, String host, int portNumber) {
// Do stuff
}
private void startClient(Scanner scan) {
// Show the JFrame on screen
// Spawn Server
}
}

the append function is run nothing appears in the text area of the jFrame
There's not enough information available in you question to ascertain why this might be happening, how ever, there are a number of important pieces of information you need to take into account.
Swing is single threaded and not thread safe
You want to, as much as possible, decouple of the code
Basically, the first point means that you shouldn't be running any long running or blocking processes within the Event Dispatching Thread AND you should not be modifying the UI (or any state the UI relies on) from outside the context of the Event Dispatching Thread
Start by taking a look at Concurrency in Swing for more details.
The second point means that, for even given part of your code, you want to be asking, "how hard would it be to replace it with some other implementation?" - If the amount of work scares you, then your code is probably to tightly coupled.
To that end, I started with...
public interface Client {
public void append(String message);
}
This is really basic, but it means that some component can send a message to some other component and neither should care about each other beyond this capability.
Next, I looked at ServerThread. Basically this class becomes responsible for the management of the Socket and delivery of the messages to the Client. Because of the requirements of Swing, I've used a SwingWorker. This allows me to run the Socket code on a background thread, but ensure that the messages are delivered to the Client within the context of the Event Dispatching Thread
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.List;
import javax.swing.SwingWorker;
public class ServerThread extends SwingWorker<Void, String> {
private String host;
private int port;
private Client client;
//Constructor
ServerThread(String host, int port, Client client) {
this.host = host;
this.port = port;
this.client = client;
}
#Override
protected void process(List<String> chunks) {
for (String message : chunks) {
client.append(message);
}
}
#Override
protected Void doInBackground() throws Exception {
try (Socket socket = new Socket(host, port)) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String text = null;
while ((text = reader.readLine()) != null) {
System.out.println(text);
if (text.equals("<stop>")) {
break;
}
publish(text);
}
}
} catch (IOException exp) {
exp.printStackTrace();
publish("Failed to establish connection to " + host + ":" + port + " - " + exp.getMessage());
}
return null;
}
}
And then the actual UI client itself...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Main {
public static void main(String[] args) {
new Main();
}
//Constructor
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ClientUI clientUI = new ClientUI();
ServerThread thread = new ServerThread("localhost", 4321, clientUI);
thread.execute();
JFrame frame = new JFrame("Client");
frame.add(clientUI);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ClientUI extends JPanel implements Client {
private JTextArea ta;
public ClientUI() {
setLayout(new BorderLayout());
ta = new JTextArea(10, 20);
add(new JScrollPane(ta));
}
#Override
public void append(String message) {
ta.append(message + "\n");
}
}
}
Not much going on here
Finally, I wrote a simple Server test the code, which simply sends the current date/time as a String to the connected client.
When I say simple, I mean simple. This is intended, by design, to tell with a single client connection and is meant only for testing the above code
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DateFormat;
import java.util.Date;
public class Server {
public static void main(String[] args) {
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
try (ServerSocket server = new ServerSocket(4321)) {
Socket socket = server.accept();
System.out.println("Connected");
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
while (true) {
System.out.println("Write >> ");
writer.write(format.format(new Date()));
writer.newLine();
writer.flush();
Thread.sleep(1000);
}
}
} catch (IOException | InterruptedException exp) {
exp.printStackTrace();
}
}
}
To test it all, start the Server and then run the Main class

Related

Chat Program: Client to Server Connectivity Issue

Project Summary
Goal: A simple application that connects a client to a server hosted on one computer and allows that client from another computer to send chat messages to everyone on that specified server.
Class ClientWindow: Runs an application that prompts the user to enter in a server ID and port. Once entered, it starts the chat program.
Problem:
For some reason unknown to me, the chat program ONLY works when connecting to a server that you've created on your own computer. Other clients from other computers cannot connect to that server.
Possible reasons for problem:
I might have incorrectly constructed the server's receiving/sending sockets
I might have incorrectly constructed the client's receiving/sending sockets
Something is getting wonky in the packets being sent between client and server
Somehow IP addresses for the sockets are being defined incorrectly
Here is the code for the chat program.
Start server
This class starts the server on the specified port. (12348 in this instance)
package server;
public class ChatServer {
public static void main(String[] args) {
// TODO Auto-generated method stub
Server.start(12348);
}
}
Server
This is the class that creates the server and listens for client connections and messages.
package server;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
public class Server {
private static DatagramSocket socket;
private static boolean running;
private static int ClientID; // Ensures that no two users have the same client ID
private static ArrayList<ClientInfo> clients = new ArrayList<ClientInfo>();
public static void start(int port) {
try {
socket = new DatagramSocket(port);
System.out.println("Application Starting...");
running = true;
listen();
System.out.println("Server started on port: " + port);
} catch (Exception e) {
System.out.println("Failed somewhere");
e.printStackTrace();
}
}
private static void broadcast(String message) {
for (ClientInfo info : clients) {
send(message, info.getAddress(), info.getPort());
}
}
private static void send(String message, InetAddress address, int port) {
try {
message += "\\e";
byte[] data = message.getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
socket.send(packet);
System.out.println("Sent message to," + address.getHostAddress() + ":" + port);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void listen() {
Thread listenThread = new Thread("ChatProgram Listener Thread") {
public void run() {
try {
while(running) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
socket.receive(packet);
String message = new String(data);
//Identify where the end of the message is
message = message.substring(0, message.indexOf("\\e"));
//Manage message
if(!isCommand(message, packet)) {
broadcast(message);
}
}
} catch(Exception e){
e.printStackTrace();
}
}
}; listenThread.start();
}
/*
* SERVER COMMAND LIST
* \con:[name] -> Connects client to server
* \dis:[id] -> Disconnects client from server
*
*
*
*/
private static boolean isCommand(String message, DatagramPacket packet) {
if (message.startsWith("\\con:")) {
// RUN CONNECTION CODE
String name = message.substring(message.indexOf(":") + 1);
clients.add(new ClientInfo(name, ClientID++, packet.getAddress(), packet.getPort()));
broadcast("User " + name + " Connected!");
return true;
}
if (message.startsWith("\\dis:")) {
// RUN DISCONNECTION CODE
return true;
}
return false;
}
public static void stop() {
running = false;
}
}
Start Client
Starts the client application.
package client;
import java.awt.EventQueue;
import java.awt.Frame;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.awt.event.ActionEvent;
public class ClientWindow {
private JFrame frmChatProgram;
private JTextField textField;
private static JTextArea textArea = new JTextArea();
private Client client;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
ClientWindow window = new ClientWindow();
window.frmChatProgram.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public ClientWindow() throws UnknownHostException {
initialize();
String name = JOptionPane.showInputDialog("Enter name:");
String servIp = JOptionPane.showInputDialog("Enter server IP address:");
String port = JOptionPane.showInputDialog("Enter server port:");
int parsedPort = Integer.parseInt(port);
//InetAddress inetAddress = InetAddress.getLocalHost();
client = new Client(name, servIp, parsedPort);
}
private void initialize() {
frmChatProgram = new JFrame();
frmChatProgram.setResizable(false);
frmChatProgram.setTitle("Chat Program");
frmChatProgram.setBounds(100, 100, 620, 446);
frmChatProgram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmChatProgram.setBackground(Color.WHITE);
frmChatProgram.getContentPane().setBackground(Color.DARK_GRAY);
frmChatProgram.getContentPane().setLayout(new BorderLayout(0, 0));
textArea.setForeground(Color.WHITE);
textArea.setBackground(Color.DARK_GRAY);
JScrollPane scrollPane = new JScrollPane(textArea);
frmChatProgram.getContentPane().add(scrollPane, BorderLayout.CENTER);
JPanel panel = new JPanel();
panel.setBackground(Color.GRAY);
frmChatProgram.getContentPane().add(panel, BorderLayout.SOUTH);
panel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
textField = new JTextField();
textField.setBackground(Color.WHITE);
panel.add(textField);
textField.setColumns(40);
JButton btnNewButton = new JButton("Send");
btnNewButton.addActionListener(e ->{
if (!textField.getText().equals("")) {
client.send(textField.getText());
textField.setText("");
}
});
panel.add(btnNewButton);
frmChatProgram.setLocationRelativeTo(null);
}
public static void printToConsole(String message) {
textArea.setText(textArea.getText() + message + "\n");
}
}
Client
Creates a client connection and listener for that client
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import server.ClientInfo;
public class Client {
private DatagramSocket socket;
private InetAddress address;
private int port;
private boolean running;
private String name;
public Client(String name, String address, int port) {
try {
this.name = name;
this.address = InetAddress.getByName(address);
this.port = port;
socket = new DatagramSocket();
socket.connect(this.address, port);
running = true;
listen();
send("\\con:" + name);
} catch (Exception e) {
e.printStackTrace();
}
}
public void send(String message) {
try {
if (!message.startsWith("\\")) {
message = name+": "+message;
}
message += "\\e";
byte[] data = message.getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
socket.send(packet);
System.out.println("Sent message to," + address.getHostAddress() + ":" + port);
} catch (Exception e) {
e.printStackTrace();
}
}
private void listen() {
Thread listenThread = new Thread("ChatProgram Listener Thread") {
public void run() {
try {
while (running) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
socket.receive(packet);
String message = new String(data);
// Identify where the end of the message is
message = message.substring(0, message.indexOf("\\e"));
// Manage message
if (!isCommand(message, packet)) {
ClientWindow.printToConsole(message);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}; listenThread.start();
}
private static boolean isCommand(String message, DatagramPacket packet) {
if (message.startsWith("\\con:")) {
// RUN CONNECTION CODE
return true;
}
if (message.startsWith("\\dis:")) {
// RUN DISCONNECTION CODE
return true;
}
return false;
}
}
I assume that you are asking about the possible reasons that your code is not be working:
1) I might have incorrectly constructed the server's receiving/sending sockets.
That is possible. You should be able to tell that by using a debugger to examine the packets on the server side.
2) I might have incorrectly constructed the client's receiving/sending sockets
Ditto ...
3) Something is getting wonky in the packets being sent between client and server
This is the most likely:
It could be a packet-level routing problem ... though that is likely to have broader effects.
It could be firewall issue
It could be an MTU issue
It could even be a broken switch, etc.
4) Somehow IP addresses for the sockets are being defined incorrectly
That is possible.
There are various things you could do to diagnose / eliminate the various possibilities. But this is not really a StackOverflow problem.

GUI frozen while waiting on an answer from the client

I'm currently having some issues running this small battleship program I am working on. I have two GUI, one for the server and one for the client. When I click the "Start Server" jButton, the program will freeze until it receives something from the client side.
Image of the GUI if it helps:
I have no issues unfreezing it by starting the client program, my issue is, how can I make it so that it just doesn't freeze while waiting? thanks a lot.
package battleship;
import javax.swing.JOptionPane;
import java.io.IOException;
import java.util.Scanner;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
/**
*
* #author ftonye
*/
public class BackGroundCom implements Runnable {
private int port;
private ServerSocket ss;
private Socket cs;
private Scanner reader;
private PrintStream writer;
public int missileIncomming;
public int missileOutgoing;
public Boolean dataToSend;
InetAddress sa = null;
public BackGroundCom(int port) {
this.port = port;
dataToSend = true;
missileOutgoing = 100;
startServer();
}
private void startServer() {
try {
sa = InetAddress.getLocalHost();
System.out.println(sa);
} catch (UnknownHostException ex) {
Logger.getLogger(BackGroundCom.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Server started");
try {
ss = new ServerSocket(this.port);
cs = ss.accept();
JOptionPane.showMessageDialog(null, "Server accept connection from" + cs.getInetAddress().getHostAddress());
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
}
System.out.println("Server accept connection");
}
Part of my BattleSea.java, which is where I click the button before it freezes:
btnStartServer = new JButton("Start Server");
btnStartServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
com = new BackGroundCom(Integer.parseInt(txtPortNumber.getText().toString()));
t = new Thread(com);
t.start();
}
});
I am trying to understand how to get it to never freeze. Thanks
I expect that it is the call cs = ss.accept(); that is blocking. This is going to block until the client connects to the server. You run this in response to pushing the button, because in your button action code, you construct a BackGroundCom, and that object's constructor calls startServer, which executes this accept() line directly.
It seems like you are trying to set up the BackGroundCom object so that what it does occurs in a background thread, but what I describe above all happens before you create and run the thread. Maybe what you want to do is move the startServer call into the run() method of the BackGroundCom object. I don't see a run() method in BackGroundCom, although it implements Runnable. I assume it's further down in the code. Without it, this code wouldn't even compile.
Steve is right. ServerSocket.accept(); method will block until a connection is made. You have to put it inside another Thread so it won't block the EDT(Event Dispatching Thread). EDT is where your GUI runs.
public BackGroundCom(int port) {
this.port = port;
dataToSend = true;
missileOutgoing = 100;
new Thread(() -> (startServer()).start(); // run in new thread
}

JAVA Chat app not working over internet

I created a chat app in Java it worked when i open server and clients on different terminals but same computer. Today i gave it to my friend to test it over internet and its not working(Connection timed out ,yes i am using muiltithreads). I have allowed port (i am using 4242) in my firewall and my friends. But still not working.
I have read couple of similar question asked on internet but each has different steps (none working) and also i am not getting all steps though.
Some said that router is hiding my ip address so i need to enable port forwarding (i dont know how) . Also there must be a way without it. Many software works like this but doesnt need us to enable port forwarding. Will using a mobile hotspot instead of modem work(I am so DUMB!).
i am noob in this area, studied networking in JAVA yesterday and made app yesterday night. Help me run my app over internet in simple language. Will be gratefull if it works without port forwarding and static ip address. Let me know if you need to see my code.
Server Side:
import java.io.*;
import java.net.*;
import java.util.*;
class DailyAdviceS
{
ArrayList<PrintWriter> Clients=new ArrayList<PrintWriter>();
Socket sock;
public static void main(String args[])
{
DailyAdviceS ad= new DailyAdviceS();
ad.go();
}
private void go()
{
try
{
ServerSocket server= new ServerSocket(4242);
InetAddress ip;
ip = InetAddress.getLocalHost();
System.out.println("Current IP address : " + ip.getHostAddress());
while(true)
{
sock=server.accept();
PrintWriter writer = new PrintWriter(sock.getOutputStream());
Clients.add(writer);
Thread foundR= new Thread(new nodeR(sock));
foundR.start();
System.out.println("got a connection");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void SendAll(String Chat,String name)
{
Iterator it=Clients.iterator();
while(it.hasNext())
{
try
{
PrintWriter writer= (PrintWriter)it.next();
writer.println(name+" /t "+Chat);
writer.flush();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
class nodeR implements Runnable //recieve message from clients
{
private String hostName;
private BufferedReader reader;
public nodeR(Socket s)
{
try
{
String hostName = s.getInetAddress().getHostName();
System.out.println(hostName);
InputStreamReader in= new InputStreamReader(s.getInputStream());
reader = new BufferedReader(in);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void run()
{
String Message;
try
{
String Name=InetAddress.getLocalHost().getCanonicalHostName();
SendAll(Name+" Ready","");
while(true)
{
while ((Message=reader.readLine())!=null)
{
SendAll(Message,Name);
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
CLient Side:
import java.io.*;
import java.net.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.text.*;
class DailyAdvice
{
private JTextArea ar= new JTextArea(100,100);
private JTextField field = new JTextField(17);
private JButton button;
private Socket chat;
private InputStreamReader stream;
private BufferedReader reader;
private PrintWriter writer;
public static void main(String args[])
{
DailyAdvice ad= new DailyAdvice();
ad.setnw();
ad.go();
}
private void go()
{
JFrame frame= new JFrame("Chat with RedHead");
JPanel panel= new JPanel();
ar.setLineWrap(true);
ar.setWrapStyleWord(true);
ar.setEditable(false);
JScrollPane scroll= new JScrollPane(ar);
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
panel.add(field);
DefaultCaret caret = (DefaultCaret) ar.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
button= new JButton("Send");
panel.add(button);
frame.getRootPane().setDefaultButton(button);
frame.add(scroll,BorderLayout.CENTER);
frame.add(panel,BorderLayout.SOUTH);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setBounds(50,50,300,300);
frame.setVisible(true);
Runnable r= new Recieve();
Thread send= new Thread(new Send());
Thread recieve= new Thread(r);
send.start();
recieve.start();
}
private void setnw()
{
try
{
chat = new Socket("122.176.8.153",4242);
stream= new InputStreamReader(chat.getInputStream());
reader= new BufferedReader(stream);
writer = new PrintWriter(chat.getOutputStream());
System.out.println("connection established");
}
catch(Exception e)
{
e.printStackTrace();
}
}
class Send implements Runnable
{
public void run()
{
button.addActionListener(new timetosend());
}
class timetosend implements ActionListener
{
public void actionPerformed(ActionEvent ev)
{
try
{
String msg =field.getText();
writer.println(msg);
writer.flush();
}
catch (Exception ex)
{
ex.printStackTrace();
}
field.setText("");
}
}
}
class Recieve implements Runnable
{
public void run()
{
try
{
String input;
while ((input= reader.readLine())!=null)
{
String[] result=input.split("/t");
ar.append(result[0]+" : "+result[1]+'\n');
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
}
Please make sure your application is not using the private IP to connect to your server if accessing over the internet. you can check your PC's public IP from the site below which is currently allocated to your PC, and can use this in your client apps.
And also make sure you have configure the port in port forwarding in your switch/router and if it is not allowed by your ISP, you can use any port forwarding software on your PC to do that.
http://www.get-myip.com/

Sending messages to clients TCP connection fails with an nullpointexception [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
Hi all :) Sorry for this really long question but this needs some explaination.
I was given an assignment where i have to turn a very simple game into a 2 player multiplayer game. The reason why we have to make this game is to learn more about threads and concurrency. I have never worked with concurrency nor with multiple threads.
My idea is to create a TCP server like i have done in GameServer.java where i create a new ServiceObject for each player. I create a thread for each ServiceObject where i will recieve, handle and send commands from a client.
Gameserver.java
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class GameServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(6789);
System.out.println("Waiting for clients to connect . . . ");
Socket s1 = server.accept();
System.out.println("Clients connected.");
PlayerService servicep1 = new PlayerService(s1);
Thread t1 = new Thread(servicep1);
Socket s2 = server.accept();
System.out.println("Clients connected.");
PlayerService servicep2 = new PlayerService(s2);
Thread t2 = new Thread(servicep2);
t1.start();
t2.start();
servicep1.sendDataToClient("ready");
servicep2.sendDataToClient("ready");
}
}
PlayerService.java
package server;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingQueue;
import game2016.Player;
public class PlayerService extends Thread {
private Socket s;
private PlayerService opponent;
private Scanner in;
private PrintWriter out;
public PlayerService(Socket aSocket) {
this.s = aSocket;
}
public void setOpponent(PlayerService opponent) {
this.opponent = opponent;
}
public void run() {
try {
in = new Scanner(s.getInputStream());
out = new PrintWriter(s.getOutputStream());
try {
doService();
} finally {
// s.close();
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
public void doService() throws IOException {
while (true) {
if (!in.hasNext()) {
return;
}
String command = in.next();
if (command.equals("QUIT")) {
return;
} else
recieveFromClient(command);
}
}
public void recieveFromClient(String command) throws IOException {
System.out.println(command);
if(command.equals("player")) {
String newPlayerName = in.next();
int xPos = in.nextInt();
int yPos = in.nextInt();
String direction = in.next();
// sendDataToOpponent("addOpponent " + newPlayerName + " " + xPos + " " + yPos + " " + direction);
}
}
public void sendDataToClient(String response) {
out.write(response + "\n");
out.flush();
}
public void sendDataToOpponent(String response) {
opponent.sendDataToClient(response);
}
}
To send data from one client to another client i have a reference to the opponents servicelayer as i can invoke the sendDataToOpponent() method to send data to him and if the server have to communicate i can just invoke sendDataToClient() from the server.
My problem is that i want to postpone opening my clients GUI to both clients have connected.
Main.java(Client) - GUI code have been left out
private static Socket s;
private static InputStream instream;
private static OutputStream outstream;
private static Scanner in;
private static PrintWriter out;
private static boolean isOpponentConnected;
public static void main(String[] args) throws Exception {
openConnection();
reciever();
waitOpponentConected();
launch(args);
}
public static void waitOpponentConected() throws Exception {
while(!isOpponentConnected) {
System.out.println("Waiting for opponent");
Thread.sleep(2000);
}
System.out.println("Opponent is ready now");
}
public static void openConnection() throws IOException {
s = new Socket("localhost", 6789);
System.out.println("Connection established");
instream = s.getInputStream();
outstream = s.getOutputStream();
in = new Scanner(instream);
out = new PrintWriter(outstream);
}
public static void responseFromServer() throws IOException {
try {
while(in.hasNext()) {
String response = in.next();
if(response.equals("ready")) {
isOpponentConnected = true;
System.out.println("Ready");
}
}
} catch (Exception e) {
}
}
public static void reciever() {
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
while(true) {
responseFromServer();
}
}
};
new Thread(task).start();
}
public static void sendCommandToServer(String command) throws IOException {
out.print(command + "\n");
out.flush();
}
I've created a Thread to recieve commands from the server, and when both clients have connected to the server it sends a string 'ready' to each of the clients. My thought was that The Main-thread sleeps till isOpponentConnected is true.
But my gameserver fails and prints out a nullpointer exception when the second clients connects to the server. I've spend to days reading and trying to fix this bug. When i run the code in debug mode, both clients recieves the ready signal and the GUI starts for both clients.
Exception in thread "main" java.lang.NullPointerException
at server.PlayerService.sendDataToClient(PlayerService.java:67)
at server.GameServer.main(GameServer.java:23)
Can you guys see anything i'm obviously doing wrong?
I think this queston is interesseting because it's not just the nullpointerexception, it's about structering TCP server-client relationships and the chain when things are initialized and ready when threads and connections are made.
It should be fixable from inside the PlayerService.java class you have posted.
I suggest moving:
in = new Scanner(s.getInputStream());
out = new PrintWriter(s.getOutputStream());
from public void run() to your PlayerService constructor:public PlayerService(Socket aSocket)
It looks like the function sendDataToClient is trying to use the out variable before it gets initialised.

Stuck with Multi-Client Chat Application

I'm trying to make a MultiClient Chat Application in which the chat is implemented in the client window. I've tried server and client code for the same. I've got two problems:
A. I believe the code should work but, server to client connections are just fine but information isn't transferred between clients.
B. I need a way to implement private one-to-one chat in case of more than two clients, I've used a class to store the information of the Socket object returned for each connection being established, but I can't figure out how to implement it.
The server code is:
import java.io.*;
import java.net.*;
class ClientInfo {
Socket socket;
String name;
public ClientInfo(Socket socket, String name) {
this.socket = socket;
this.name = name;
}
}
public class server {
private ObjectInputStream input[] = null;
private ObjectOutputStream output[] = null;
private String value = null;
private static ServerSocket server;
private Socket connection = null;
private static int i = -1;
public static void main(String args[]) {
try {
server = new ServerSocket(1500, 100);
while (true) {
System.out.println("Waiting for connection from client");
Socket connection = server.accept();
i++;
System.out.println("Connection received from " + (i + 1) + " source(s)");
//System.out.println(i);
new ClientInfo(connection, "Client no:" + (i + 1));
innerChat inc = new server().new innerChat(connection);
}
} catch (Exception e) {
System.out.println("Error in public static void main! >>>" + e);
}
}// end of main!!!
class innerChat implements Runnable {
private Socket connection = null;
public innerChat(Socket connection) {
this.connection = connection;
Thread t;
t = new Thread(this);
t.start();
}
public void run() {
try {
output[i] = new ObjectOutputStream(connection.getOutputStream());
output[i].flush();
input[i] = new ObjectInputStream(connection.getInputStream());
} catch (Exception e) {
}
}
}
}
And the client code is
import java.net.*;
import java.io.*;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.*;
import java.awt.event.*;
public class ChatappClient {
private static int port = 1500;
JFrame window = new JFrame("Chat");
JButton sendBox = new JButton("Send");
JTextField inputMsg = new JTextField(35);
JTextArea outputMsg = new JTextArea(10, 35);
private ObjectInputStream input;
private ObjectOutputStream output;
public static void main(String[] args) throws Exception {
ChatappClient c = new ChatappClient();
c.window.setVisible(true);
c.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
c.run();
}
public ChatappClient() {
inputMsg.setSize(40, 20);
sendBox.setSize(5, 10);
outputMsg.setSize(35, 50);
inputMsg.setEditable(true);
outputMsg.setEditable(false);
window.getContentPane().add(inputMsg, "South");
window.getContentPane().add(outputMsg, "East");
window.getContentPane().add(sendBox, "West");
window.pack();
sendBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
output.writeObject(inputMsg.getText());
outputMsg.append("\n" + "Client>>>" + inputMsg.getText());
output.flush();
} catch (IOException ie) {
outputMsg.append("Error encountered! " + ie);
}
inputMsg.setText("");
}
});
inputMsg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
output.writeObject(inputMsg.getText());
outputMsg.append("\n" + "Client>>>" + inputMsg.getText());
output.flush();
} catch (IOException ie) {
outputMsg.append("Error encountered! " + ie);
}
inputMsg.setText("");
}
});
}
private void run() throws IOException {
Socket clientSocket = new Socket("127.0.0.1", port);
output = new ObjectOutputStream(clientSocket.getOutputStream());
output.flush();
input = new ObjectInputStream(clientSocket.getInputStream());
outputMsg.append("I/O Success");
String value = null;
while (true) {
try {
value = (String) input.readObject();
} catch (Exception e) {
}
outputMsg.append(value + "\n");
}
}
}
Your code looks like it could be improved quite a bit. Your main method for instance should have none of that code in it. It should start your Server class, and that's it (and note that class names should begin with an upper case letter as per Java standards which I strongly advise you to follow).
I'm trying to make a MultiClient Chat Application in which a Server does nothing but listen and create connections.
The Server is going to have to do more than that. It will need to create Clients, it will need to maintain a collection such as an ArrayList of Clients such as an ArrayList<ChatappClient> Otherwise how do you expect the Server to connect two Clients together?
I think that in all you're going to need to think the structure and connections of this program out in more depth before starting to write code.

Categories

Resources