I've got codes of a server and clients written on Java. But the question is how to run multiple clients on DIFFERENT console-windows with Eclipse when server is running? Thx for helping!
(solved!!)
UPDATE**
Another question: I'll create a new question
Server:
import java.net.*;
import java.io.*;
public class ATMServer {
private static int connectionPort = 8989;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(connectionPort);
} catch (IOException e) {
System.err.println("Could not listen on port: " + connectionPort);
System.exit(1);
}
System.out.println("Bank started listening on port: " + connectionPort);
while (listening)
new ATMServerThread(serverSocket.accept()).start();
serverSocket.close();
}
}
ServerThread:
import java.io.*;
import java.net.*;
public class ATMServerThread extends Thread {
private Socket socket = null;
private BufferedReader in;
PrintWriter out;
public ATMServerThread(Socket socket) {
super("ATMServerThread");
this.socket = socket;
}
public void run(){
}
}
}
Client: (**UPDATE)
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ATMClient {
private static int connectionPort = 8989;
public static void main(String[] args) throws IOException {
Socket ATMSocket = null;
PrintWriter out = null;
BufferedReader in = null;
String adress = "";
try {
adress = "127.0.0.1";
} catch (ArrayIndexOutOfBoundsException e) {
System.err.println("Missing argument ip-adress");
System.exit(1);
}
try {
ATMSocket = new Socket(adress, connectionPort);
out = new PrintWriter(ATMSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader
(ATMSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Unknown host: " +adress);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't open connection to " + adress);
System.exit(1);
}
out.close();
in.close();
ATMSocket.close();
}
You can run as many socket clients from Eclipse provided that you pass user-defined ip/port info as command arguments from main() under Program Arguments tab in Run Configuration dialog for that program inside Eclipse rather than using some hardwired values for ip/port.
To create multiple console views (via separate Console View tabs rather than clicking on each instance), you need to create a new console view for each target instance in Eclipse Debug View mode; to achieve this, you need to select "New Console View" (from the icon button with the plus symbol to the far right of the Console View) and assign which program instance to view from each new console.
Another question: if I have to change something on ServerThread, for example, add a title, is that possible to execute that without restart the server?
Which title? I don't see any GUI code for the ServerThread code snippet. Do you mean the title name of the Console view tab?
Related
I have created client Server program in java. While I run program I should get port number and IP address but I am getting an error while I run Client.java. Below is my both files.
Server.java
package serverpro;
import java.io.*;
import static java.lang.ProcessBuilder.Redirect.to;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server extends Thread {
public static final int PORT_NUMBER = 12345;
protected Socket socket;
public static void main(String[] args) {
ServerSocket server = null;
try {
server = new ServerSocket(PORT_NUMBER);
while (true) {
new Server(server.accept());
}
}
catch(IOException ex) {
System.out.println("Unable to start server or acccept connections ");
System.exit(1);
}
finally {
try {
server.close();
}
catch(IOException ex) {
// not much can be done: log the error
// exits since this is the end of main
}
}
}
private Server(Socket socket) {
this.socket = socket;
start();
}
// the server services client requests in the run method
public void run() {
InputStream in = null;
OutputStream out = null;
BufferedReader inReader = new BufferedReader(newInputStreamReader(in));
// the constructor argument “true” enables auto-flushing
PrintWriter outWriter = new PrintWriter(out, true);
outWriter.println("Echo server: enter bye to exit.");
//outWriter.println(“Echo server: enter ‘bye’ to exit.”);
while (true) {
// readLine blocks until a line-terminated string is available
String inLine;
try {
inLine = inReader.readLine();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
// readLine returns null if the client just presses <return>
try {
in = socket.getInputStream();
out = socket.getOutputStream();
// ... do useful stuff ...
}
catch(IOException ex) {
System.out.println("Unable to get Stream from ");
}
finally {
try {
in.close();
out.close();
socket.close();
}
catch(IOException ex) {
// not much can be done: log the error
}
}
}
}
}
Client.java
package serverpro;
import java.io.*;
import java.net.*;
public class Client {
public static void main(String args[]) throws IOException {
new Client(args[0]);
}
public Client(String host) throws IOException {
Socket socket;
try {
socket = new Socket(host, Server.PORT_NUMBER);
}
catch(UnknownHostException ex) {
System.out.println(host + " is not a valid host name.");
return;
}
catch(IOException ex) {
System.out.println("Error connecting with" + host);
return;
}
// … initialize model, GUI, etc. ...
InputStream in = null;
OutputStream out = null;
try {
in = socket.getInputStream();
out = socket.getOutputStream();
// ... do useful stuff ...
}
finally {
try {
in.close();
out.close();
socket.close();
}
catch(IOException ex) {
// not much can be done ...
}
}
}
}
Here is the error code I am getting while running client.java file
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at serverpro.Client.main(Client.java:13)
/Users/Puja Dudhat/Library/Caches/NetBeans/8.2/executor- snippets/run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)
Your code expects one argument passed into the main method, which appears to be your client port, stored at args[0]. Therefore, you have to provide one to the main method. An example for setting port=12345:
java Server 12345
If you'd need more arguments, (e.g. a value at args[1]), then simply add another argument when launching main:
java Server 12345 secondArg
Assuming you are not passing required command-line argument. When I ran this code it did run fine, provided the argument required is passed or hard-coded; namely:
public static void main(**String args[]**) throws IOException {
new Client(**args[0]**);
}
if you are running both server and client on same machine then you can pass localhost as command line argument
java Client localhost
Alternatively, you can hard code host value(note : this is not good practice though),
public static void main(String args[]) throws IOException {
new Client("localhost");
}
Also as a suggestion, you can use ide like eclipse or intellij to debug your code step by step. you can go through online video tutorials for java and many are available on youtube
Note: I found a similar question here:
How to close port after using server sockets
But did not find any satisfactory answer there.
Here is my code for the client program:
package hf;
import java.io.*;
import java.net.*;
public class DailyAdviceClient
{
private static final int chatPort = 4242;
public static void main(String[] args)
{
DailyAdviceClient client = new DailyAdviceClient();
client.go();
}
private void go()
{
try
{
Socket socket = new Socket("127.0.0.1",chatPort);
InputStreamReader inputStream = new InputStreamReader(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStream);
String advice = bufferedReader.readLine();
System.out.println("Advice received by the client for today is "+advice);
bufferedReader.close();
}
catch(Exception e)
{
System.out.println("Failed to connect to the server");
}
}
}
And here is the code for the server program:
package hf;
import java.io.*;
import java.net.*;
public class DailyAdviceServer
{
private String[] adviceList = {"Take smaller bites",
"Go for the tight jeans. No they do NOT make you look fat.",
"One word: inappropriate",
"Just for today, be honest. Tell your boss what you *really* think",
"You might want to rethink that haircut."};
private static final int chatPort = 4242;
public static void main(String[] args)
{
DailyAdviceServer server = new DailyAdviceServer();
server.go();
}
private void go()
{
try
{
ServerSocket serverSocket = new ServerSocket(chatPort);
while(true)
{
Socket socket = serverSocket.accept();
PrintWriter writer = new PrintWriter(socket.getOutputStream());
String advice = getTodaysAdvice();
writer.println(advice);
writer.close();
}
}
catch(Exception e)
{
System.out.println("Error in establishing connection with the client");
}
}
private String getTodaysAdvice()
{
String advice = null;
int randomIndex = (int) (Math.random()*adviceList.length);
advice = adviceList[randomIndex];
return advice;
}
}
In the application, whenever a client program connects to the server program, it receives a String that contains advice for the day.
When I run
netstat -an
In the command prompt of my Windows computer as suggested in one of the answers in the aforementioned link, I get a message that the port 4242 is
LISTENING
How do I close the port and make it available for future re-use?
To get rid of the LISTENING port you have to call serverSocket.close().
You have to use socket.close() after closing the writer and bufferedReader. So the Port will be free for another communication.
I am trying to learn some network programming, so I thought a good place to start would be with sockets and how to use them. Although it seems that I have hit a brick wall, but the issue does not have as much to do with sockets as it does with checking a socket for two things at (seemingly)the same time.
package com.redab.server;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class server implements Runnable {
private final int portNumber = 4444;
private ServerSocket serverSocket;
private Socket clientSocket;
private Thread thread;
private PrintWriter out;
private BufferedReader in;
private BufferedReader stdIn;
private String incomingText;
private String outgoingText;
private Boolean isRunning = false;
public server() {
thread = new Thread(this, "serverThread");
try {
serverSocket = new ServerSocket(portNumber);
clientSocket = serverSocket.accept(); // Unless socket connection is made, probram will not proceed beyond this line.
System.out.println("connected");
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port " + portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
private synchronized void start() {
thread.start();
isRunning = true;
}
private synchronized void stop() {
try {
thread.join();
isRunning = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
System.out.println("running...");
while (isRunning) {
incoming();
outgoing();
}
}
private synchronized void incoming() {
System.out.println("Incoming");
try {
if ((incomingText = in.readLine()) != null) {
System.out.println(incomingText);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private synchronized void outgoing() {
System.out.println("outgoing");
try {
if ((outgoingText = stdIn.readLine()) != null) {
out.println("Server: " + outgoingText);
System.out.println("Server: " + outgoingText);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
server server = new server();
server.start();
}
}
My problem is the following:
How do I make it so both the method incoming() and outgoing() is ran constantly when I execute the code?
I did google a bit and threads seems to be the solution, so I tried creating a thread which is supposed to run both methods for me. But I run into the same problem again, the code gets stuck in the incoming() method when I want it to simply check this statement ((incomingText = in.readLine()) != null) and then proceed to the method outgoing(). I suspect I might need two threads, one of which checks for incoming messages through the socket and the other checks for outgoing messages that are typed into the console(System.in).
I suspect I might need two threads, one of which checks for incoming messages through the socket and the other checks for outgoing messages that are typed into the console(System.in)
You are right, you need two threads, one per each task.
You might want to check if there is data available to read by using the in.ready() method first. If available, you can read the data using in.readLine(), else do nothing. Currently, in.readLine() blocks because there is no input available on the socket.
So I don't know who to go about creating a multithreaded server. I have client and server working fine together but can't introduce multiple clients properly. Here is my Server code:
package dod;
import java.net.*;
import java.io.*;
import dod.game.GameLogic;
public class Server{
Server(GameLogic game, int port) throws IOException{
ServerSocket ss = null;
Socket sock = null;
try{
ss = new ServerSocket(4444);//port no.
while(true){
try{
sock = ss.accept();
ClientThread thread = new ClientThread(game, sock);
System.out.println("Adding new player...");
thread.run();
}catch(final Exception e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
}catch(Exception d){
System.out.println(d);
}finally{
if(ss!=null){
ss.close();
}
}
}
}
Here is my thread class:
package dod;
import java.io.*;
import java.net.Socket;
import dod.game.GameLogic;
import dod.game.PlayerListener;
public class ClientThread extends CommandLineUser implements PlayerListener, Runnable{
DataInputStream in;
PrintStream out;
// The game which the command line user will operate on.
// This is private to enforce the use of "processCommand".
ClientThread(GameLogic game, Socket sock) {
super(game);
try{
in = new DataInputStream(sock.getInputStream());
out = new PrintStream(sock.getOutputStream());
}catch(IOException ioe){
System.out.println(ioe);
}
game.addPlayer(this);
}
/**
* Constantly asks the user for new commands
*/
public void run() {
System.out.println("Added new human player.");
// Keep listening forever
while(true){
try{
// Try to grab a command from the command line
final String command = in.readLine();;
// Test for EOF (ctrl-D)
if(command == null){
System.exit(0);
}
processCommand(command);
}catch(final RuntimeException e){
System.err.println(e.toString());
System.exit(1);
} catch (final IOException e) {
System.err.println(e.toString());
System.exit(1);
}
}
}
/**
* Outputs a message to the player
*
* #param message
* the message to send to the player.
*/
public void outputMessage(String message) {
out.print(message);
}
}
Not asking for new code as such, just need pointers as to what I need to do have multiple client connection at the same time! Thanks to anyone who helps out!
To start, add new Thread(clientThread) in the server and call start() on it - as is everything's happening on the same thread.
public class Server{
Server(GameLogic game, int port) throws IOException{
ServerSocket ss = null;
Socket sock = null;
try{
ss = new ServerSocket(4444);//port no.
while(true){
try{
sock = ss.accept();
ClientThread thread = new ClientThread(game, sock);
System.out.println("Adding new player...");
thread.start(); //you have to use start instead of run method to create multi thread application.
}catch(final Exception e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
}catch(Exception d){
System.out.println(d);
}finally{
if(ss!=null){
ss.close();
}
}
}
}
You have to use start instead of run method to create multi thread application.
If you want to send messages about new connections you have to hold sock in a list and when a new connection accepted send message to all socket object in list. (server broadcasts to all connected sockets)
I hope it helps.
Here is the code
I have written a server and client. But when i run them, (as you can see in the last program), I get the following error:
Whoop s! java.net.BindException: Address already in use 6666
6666 is the port no. i specified.
import java.net.*;
import java.io.*;
import java.lang.*;
public class processSendHelper
{
Process p;
String address;
int port;
long msg_data;
processSendHelper(int pid, int current_round, long address, long msg_data, int port)
{
try
{
ServerSocket sSoc = new ServerSocket(port);
Socket inSoc = sSoc.accept();
msg_Thread msgT = new msg_Thread(inSoc, msg_data);
msgT.start();
Thread.sleep(5000);
sSoc.close();
}
catch(Exception e)
{
System.out.println("Whoop s! " + e.toString());
}
}
}
/* sends out (or rather just makes available) the provided msg
* */
class msg_Thread extends Thread
{
Socket threadSoc;
long msg_data;
msg_Thread (Socket inSoc, long msg_data)
{
threadSoc = inSoc;
this.msg_data = msg_data;
}
public void run()
{
try
{
PrintStream SocOut = new
PrintStream(threadSoc.getOutputStream());
SocOut.println(msg_data);
}
catch (Exception e)
{
System.out.println("Whoops!" + e.toString());
}
try
{
threadSoc.close();
}
catch (Exception e)
{
System.out.println("Oh no! " +
e.toString());
}
}
}
import java.net.*;
import java.io.*;
public class processReceiveHelper
{
Socket appSoc;
BufferedReader in;
String message;
String host;
int port;
processReceiveHelper(String host,int port)
{
try
{
appSoc = new Socket(host,port);
in = new BufferedReader(new InputStreamReader(appSoc.getInputStream()));
message = in.readLine();
System.out.println(message);
/* Tokenizer code comes here
* Alongwith the code for
* updating the process object's
* data
* */
}
catch (Exception e)
{
System.out.println("Died... " +
e.toString());
}
}
}
public class Orchestrator
{
public static void main(String[] args)
{
processSendHelper psh = new processSendHelper(1, 2, 1237644, 6666, 2002);
processReceiveHelper prh = new processReceiveHelper("localhost", 2002);
}
}
EDIT:
I found the problem. The reason was that i was running both the server and client from the same main program.
the following worked:
That means there is already an application operating on port 6666 preventing your Java application using it. However, it is equally possible there is a running process of your Java application still holding onto 6666. Terminate any running java processes and try re-running the code - if it still fails then you have some other application using 6666 and you would be better using a different port.
That means that the port 6666 is already being used. There are two main causes/solutions for this:
Some other program is using that port. Solution: Choose a different port.
Your old Java program is hanging and still "using" that port. Close all of your hanging Java programs and try again. If that doesn't solve your problem, choose a different port.
Does it happen when you run the program for the second time? You may want to setReuseAddress(true) on this socket.