I am fairly raw. I am trying to write a Java class to interact with Telnet. I saw that Apache Commons and Jsacpe had APIs. I am using Jscape's Sinetfactory. The Telnet I am connecting to sends a prompt to enter 'User name?:' as soon as telnet.connect() occurs. I am required to verify that this prompt is actually happening so I do not just write the answer when something else may happen. I am inexperienced with this and am sure there is a simple answer, just wondering if anyone might be able to help.
Here is what I have, its a bit sloppy because I've been playing around for awhile not sure how to actually read the last characters from the stream.
import com.jscape.inet.telnet.*;
public class TelnetTest extends TelnetAdapter {
private final static String USER = "xxx\r";
private final static String PWORD = "yyy\r";
private final static String COMMAND = "zzz\r";
private final static byte[] USER_BYTE = USER.getBytes();
private final static byte[] PWORD_BYTE = PWORD.getBytes();
private final static byte[] COMMAND_BYTE = COMMAND.getBytes();
private Telnet telnet = null;
private OutputStream output = null;
private static BufferedReader reader = null;
private boolean connected = false;
private String hostname = "qqq";
//TelnetInputStream tis = null; NOT IN USE AS OF NOW
public TelnetTest() throws IOException, TelnetException {
// create new Telnet instance
telnet = new Telnet(hostname);
// register this class as TelnetListener
telnet.addTelnetListener(this);
// establish Telnet connection
telnet.connect();
connected = true;
output = telnet.getOutputStream();
// HERE IS WHERE I NEED HELP, NOT SURE HOW TO CHECK STREAM
String str = null;
if ((str = reader.readline()).equals("User name?:")) {
telnet.getOutputStream().write(USER_BYTE);
}
// SAME CHECK WOULD HAPPEN HERE FOR "Password"
telnet.getOutputStream().write(PWORD_BYTE);
// ANOTHER SIMILAR CHECK HERE
telnet.getOutputStream().write(COMMAND_BYTE);
// sends all data entered at console to Telnet server
String input = null;
while ((input = reader.readLine()) != null) {
if (connected) {
((TelnetOutputStream) output).println(input);
} else {
break;
}
}
}
public boolean streamContainsString(Reader reader, String searchString)
throws IOException {
Scanner streamScanner = new Scanner(reader);
if (streamScanner.findWithinHorizon(searchString, 0) != null) {
return true;
} else {
return false;
}
}
// Invoked when Telnet socked is connected.
public void connected(TelnetConnectedEvent event) {
System.out.println("Connected");
}
// Invoked when Telnet socket is disconnected. Disconnect can
public void disconnected(TelnetDisconnectedEvent event) {
connected = false;
System.out.print("Disconnected. Press enter key to quit.");
}
// Invoked when Telnet server requests that the Telnet client begin performing specified TelnetOption.
public void doOption(DoOptionEvent event) {
// refuse any options requested by Telnet server
telnet.sendWontOption(event.getOption());
}
// Invoked when Telnet server offers to begin performing specified TelnetOption.
public void willOption(WillOptionEvent event) {
// refuse any options offered by Telnet server
telnet.sendDontOption(event.getOption());
}
// Invoked when data is received from Telnet server.
public void dataReceived(TelnetDataReceivedEvent event) {
// print data recevied from Telnet server to console
System.out.print(event.getData());
}
public Telnet getTelnet() {
return telnet;
}
// starts console program
public static void main(String[] args) {
try {
// create BufferedReader to read data from console
reader = new BufferedReader(new InputStreamReader(System.in));
// create new TelnetExample instance
TelnetTest example = new TelnetTest();
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
}
If you are reading/writing Strings then you should always use Reader and Writer. BufferedReader allows you to do line operations. So a BufferedReader wrapped around an Reader (around a InputStreamReader) will allow you to do a readLine() call to get the line of input from the connection:
BufferedReader reader =
new BufferedReader(new InputStreamReader(telnet.getInputStream()));
To write to the connection you would use a Writer around a OutputStreamWriter:
Writer writer = new OutputStreamWriter(telnet.getOutputStream()));
I'm not sure if that works with the stream from Telnet but it works with a raw Socket. You then could do something like the following pseudo code:
while (true) {
read a line from the server
some sort of if/then/else to test for the output
write your username/password or whatever is appropriate for the connection
repeat until some logout or IOException...
}
The Apache Telnet class has a number of interesting listeners and other handlers which you could use if you wanted to but the learning curve may be more. Here's a good sample application using TelnetClient:
http://www.java2s.com/Code/Java/Network-Protocol/ExampleofuseofTelnetClient.htm
Related
I started to study java last month, and now I'm trying to write a simple chat program but I encountered something strange, and I was curious for the reason behind it.
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) throws IOException {
String text = "";
ServerSocket ss = new ServerSocket(21025);
while (true){
System.out.println("Waiting...");
Socket s1 = ss.accept();
System.out.println("Connection accepted from "+s1.getInetAddress());
PrintStream pout = new PrintStream(s1.getOutputStream());
pout.println("Connected to the server");
new Thread(new Ricevitore(s1)).start();
}
}
}
public class Ricevitore implements Runnable {
String text = "";
Socket skt;
public Ricevitore(Socket skt){
this.skt = skt;
}
#Override
public void run() {
while (!text.equalsIgnoreCase("end")) {
try {
InputStream in = skt.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
text = br.readLine();
if (!text.equalsIgnoreCase("end"))
System.out.println(text);
}
catch (IOException e){}
}
}
}
public class Client {
public static void main(String[] args) throws IOException {
//Create a socket
try (Socket s = new Socket("127.0.0.1", 21025)) {
String text="";
while(!text.equalsIgnoreCase("end")) {
//Allows messages from server
InputStream in = s.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
if (br.ready()) {
Scanner server = new Scanner(br);
String testoServer = br.readLine();
System.out.println(testoServer);
}
//Allows to send text to the server
OutputStream out = s.getOutputStream();
PrintStream pout = new PrintStream(out);
Scanner tastiera = new Scanner(System.in);
text = tastiera.nextLine();
pout.println(text);
}
}
}
}
This is the complete program for the moment, my question is this: Since I wanted to avoid printing the word "end" to close the program, I inserted
if (!text.equalsIgnoreCase("end"))
but after that the server does not display the message "connected to server" unless I first input something through the client.
If I comment out that if statement, both messages "Connection accepted" and "Connected to server" got printed at the same time as intended.
I don't know if my question is clear, and I'm rather interested in learning why something like this happens.
If there are other things which any of you think is wrong I'll be happy to here about them.
I have only a wild guess which looks probable though.
In your client you read the message from the server if br.ready() returns true. It may happen that this function returns false, and the client goes to waiting for user's input.
After you send a message from the client to the server, the client repeats the test and now gets the message from the server.
I cannot explain why removing if (!text.equalsIgnoreCase("end")) in server's code makes the issue go away. That line isn't even executed until you send a message from the client.
So I think it's just a coincidence. There are two processes involved, and the outcome depends on how fast code executes in either process.
I ran your example many times, and once I did not receive the greeting from the server even though the if above was in its place.
A general suggestion for your code: you don't need to create input/output streams as well as Scanner on each iteration, you should do it only once.
To end communication session, you can just close PrintStream in your client as soon as you receive end from user. Your server will get null from br.readLine(). At this point, you close br and complete run().
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.
EDIT: I have corrected the mistake below in the code, by adding a line into the server code
I'm trying to write some socket code that will allow me to send data from one computer to another for a game (which for simplicity's sake, we can think of as tic-tac-toe, not much data needs to be sent, just a couple of numbers). In order to achieve this I have written two classes, Server and Client. At the moment I am testing through the localhost using port 1234, and I am only using one single instance of the program (though the same problem occurs when trying to use two instances).
Firstly here's the code, and then I can go into more depth about the problem, and what testing I've done to attempt to work out what is going wrong:
public class Server
{
private ServerSocket server;
private Socket socket;
private Client socketHandler;
private static final int DEFAULT_PORT = 1234;
public Server() { this(DEFAULT_PORT); }
public Server(int port)
{
Thread thread = new Thread()
{
public void run()
{
try
{
System.out.println("Attempting to Establish Connection");
server = new ServerSocket(port);
socket = server.accept();
socketHandler = new Client(port, socket); //THIS LINE ADDED
System.out.println("Server Online!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
}
//ADJUSTED
Client getSocketHandler()
{
return socketHandler;
}
public void kill()
{
try
{
if (socket != null) socket.close();
if (server != null) server.close();
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
socket = null;
server = null;
}
}
}
public class Client
{
public static final int DEFAULT_PORT = 1234;
public static final String DEFAULT_HOST = "localhost";
private static final String THUMP_THUMP = "thump thump";
private static final int PULSE = 1000;
private int port;
private String ip;
private Socket socket;
private BufferedReader input = null;
private PrintWriter output = null;
boolean closed = true;
String data = "";
public Client() { this(DEFAULT_PORT, DEFAULT_HOST, null); }
public Client(int port) { this(port, DEFAULT_HOST, null); }
public Client(int port, String ip) { this(port, ip, null); }
public Client(int port, Socket server) { this(port, DEFAULT_HOST, server); }
public Client(String ip) { this(DEFAULT_PORT, ip, null); }
public Client(String ip, Socket server) { this(DEFAULT_PORT, ip, server); }
public Client(Socket server) { this(DEFAULT_PORT, DEFAULT_HOST, server); }
public Client(int port, String ip, Socket server)
{
socket = server;
this.ip = ip;
this.port = port;
Thread thread = new Thread()
{
public void run()
{
try
{
initialise(server);
String line;
startHeartbeat();
while (isClosed()) {} //first it is closed, lets wait for it to open before we start waiting for it to close!
System.out.println("We are about to listen!");
while (!isClosed())
{
System.out.println("pre-read"); //this line was used to determine that the code was hanging on the next line
line = input.readLine(); //offending line
System.out.println("post-read"); //this line was used to determine when the block was lifted
if (line != null)// || line != THUMP_THUMP)
{
System.out.println(line);
data += line + "\n";
}
}
System.out.println(data);
kill();
System.out.println("Connection Closed!");
}
catch (SocketException e)
{
e.printStackTrace();
System.out.println("Server closed!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
}
private void initialise(Socket server)
{
try
{
if (server == null) socket = new Socket(ip, port);
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
}
catch (IOException e) { e.printStackTrace(); }
}
public boolean post(String text)
{
synchronized(this)
{
output.println(text);
output.flush();
return !output.checkError();
}
}
public void kill()
{
try
{
if (input != null) input.close();
if (socket != null) socket.close();
}
catch(IOException e) { e.printStackTrace(); }
finally
{
input = null;
socket = null;
}
}
public void killOutputStream()
{
try
{
if (output != null) output.close();
}
catch (Exception e) { e.printStackTrace(); }
finally
{
output = null;
}
}
//////////////////////////////////
///////// Socket Control /////////
//////////////////////////////////
synchronized boolean isClosed()
{
return closed;
}
synchronized void setClosed(boolean b)
{
closed = b;
}
//We need to make sure that the socket is still online, to ensure the reading stops when the connection closes.
void startHeartbeat()
{
Thread heartbeat = new Thread()
{
public void run()
{
while (output != null)
{
setClosed(post(THUMP_THUMP) ? false : true); //post returns true on success
synchronized(this)
{
try
{
this.wait(PULSE);
}
catch (InterruptedException e) {}
}
}
setClosed(true);
}
};
heartbeat.setDaemon(true);
heartbeat.start();
}
}
The Problem
When the client is started (after having created the server) it fails to read any data sent through (or even the heartbeat), in fact the code does not go past line = input.readLine() in the reading thread (which is from now on called the offending line), except it seems, until the server is disconnected (see below).
Here is the order of regular testing:
Server() is called and the resulting Server is stored in the serverConnection variable then
Client(serverConnection != null ? serverConnection.getSocket() : null) is called and the new Client is stored in clientConnection.
Because we can test whether it is working using the heartbeat no other data needs to be sent, and the server is terminated by calling serverConnection.kill() and then clientConnection.killOutputStream() after letting some time elapse.
and this is the result:
Attempting to Establish Connection Server Online!
We are about to listen!
Connection Closed!
where the empty line represents the non null data received over the course of the connection, ie that there is none.
I expect this:
Attempting to Establish Connection
Server Online!
We are about to listen!
thump thump
thump thump
thump thump (and so on, every second)
Connection closed!
I spent time performing different tests by commenting out or changing the code slightly with the same testing format (except for the special case, which is number 6) and made these observations:
Observations
Only when the socket is closed and the output stream is closed, does the program move past the offending line.
When the readline() method starts to process (shortly before the heartbeat cuts it off) it detects nothing in the stream, not even THUMP_THUMP.
When the socket is closed, but the output stream is not, the readline() method starts to process, only to detect nothing, heartbeat cuts it off. No SocketException even though it would be expected.
If the socket is NOT closed, and only the output stream is closed, a SocketException is triggered, suggesting the socket is closed.
I used netstat -an in command prompt, and when the server is started the port 1234 is LISTENING. When the client connects, it is still LISTENING, implying that there is no connection.
I set up some python code to connect to itself over port 1234,
however I made a mistake in the python code, and as such the server
didn't close, and was still open. So I decided to connect the java
client to the server and see what happens. I did this by running
Client(null) which is the client code for the non-host. It
resulted in the port reading ESTABLISHED, and the python server was
echoing back the "thump thump", and the java code was successfully
reading it. No hanging, it worked perfectly.
This leads me to believe that the problem lies in the server code, as the python server was able to communicate sucessfully with the Java client, but the Java client is unable to communicate with the Java server.
Before performing this testing I had been concentrating on the Client code, believing that it was at fault. All the questions I have found here with similar symptoms (see here, here and here, among others) have turned up blank for me, having written in their solutions (most were due to the output stream not flushing, or the \n ommitted, which I have not failed to do, or the solution not fixing my problem, and so having been removed in favor of the heartbeat in this case). I originally based my code off of this article.
After 4 days of trying to figure out this problem I am at a loss for what to do... What am I missing here? Why is the Server code not working as I expect it to? If anybody needs any more clarification on my code then please ask!
As an after-note, the testing code is run through a simple minimalistic GUI written in javafx (not fxml though), whether that would be a problem or not I'm sure, I would think not, due to it working with the Python server. This code is compiled in Java 8
I'm a little confused about why you think it would go any furthur than input.readLine() considering there is no handling of inputs/outputs on the server side....
Client/Server connections are like a game of tennis, as one side serves the other must receive the ball and then serve it back(maybe with different information). Your server side must handle the input it recieves from the start heartbeat method, and then send you back a response. the input.readLine() function blocks the thread until it receives data from the other end, so yes the code stops there and waits for your server to send the "tennis ball" back. In the server class you should add an input and output stream that handle the heart beat inputs and send back a string of data to the client.
Server:
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
String response = "thump thump";
while(true){
is.read();
os.write(response.getBytes());
os.flush();
}
with this example, the client should remain unchanged and just add the above code to your server.
I'm trying to make a networking application, for a proof of concept project.
I need to keep the connection open, the joined clients, but the while loop I'm running never gets out of the first loop.
Code:
public class comm implements Runnable {
private Socket socket;
private String line, input;
boolean sending = true;
boolean connected = false;
private int me;
private BufferedReader br;
private PrintWriter pw;
doComms(Socket server) {
socket = server;
me = Main.connected;
}
public void run() {
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream(), true);
while (true) {
System.out.println("Waiting");
readCommand();
}
} catch (Exception ex) {
System.out.println(ex);
}
}
private void readCommand() throws Exception {
String str;
while (br.readLine() != null) {
if (!connected) {
pw.println("connect");
}
str = br.readLine();
System.out.println(str);
if (str.startsWith("!START!")) {
System.out.println("User connected");
connected = true;
String[] split = str.split("#");
Main.jTable1.getModel().setValueAt(split[1], me, 2);
Main.jTable1.getModel().setValueAt(split[2], me, 3);
Main.jTable1.getModel().setValueAt("Connected...", me, 4);
}
}
}
}
Starting that code is fine, all it does is makes a new thread for each connected users, and the client software runs fine too. what am I doing wrong?
My best guess. It never gets out of the first readCommand call because readCommand itself is in an infinite loop:
while (br.readLine() != null) {
br.readLine will block until the next line from the socket input arrives. So the only way for the loop to exit is for the remote client to disconnect.
But the while loop I'm running never gets out of the first loop.
The first loop you are referring to is:
while(true) { ... }
This will never exit because true is always true.
I am having some problems figuring out this issue. I have a server that takes a string from a client, the first four characters of which act as a 'command' of sorts. rep: replaces the stored string, app: appends to it.
This works mostly fine, however when I use the rep: command, it repeats the client's string twice. So, if I inputted rep:foo the server returns 'foofoo'. I have tried analysing the code and can't see any immediate problems.
When adding some test output commands to both the server and the client, to see what the variables hold, I get the result as expected (the string input on the client minus the command characters). The code for both classes is below:
Server:
import java.io.*;
import java.net.*;
import java.util.*;
public class SynchServer
{
public static void main(String[] args) throws IOException
{
ServerSocket serverSocket = null;
final int PORT = 1234;
Socket client;
ClientHandler2 handler; // thread for client
int clientCount = 0;
//set up server socket
try
{
serverSocket = new ServerSocket(PORT);
}
catch(IOException ioEx)
{
System.out.println("Cannot open socket!");
System.exit(1);
}
// client connections and related actions:
do
{
// wait for client...
client = serverSocket.accept();
System.out.println("Client accepted...\n");
// assign client a connection number
clientCount++;
// create thread
handler = new ClientHandler2(client, clientCount);
// run thread
handler.start();
}while(true);
}
}
class ClientHandler2 extends Thread
{
// declare thread variables
private Socket client;
private Scanner input;
private PrintWriter output;
private static String text = "";
int clientNum; // picked up from main
// constructor - set up socket and streams
public ClientHandler2(Socket socket, int clientCount)
throws IOException
{
client = socket;
clientNum = clientCount;
// streams...
// from client
input = new Scanner(client.getInputStream());
// to client
output = new PrintWriter(client.getOutputStream(), true);
}
// thread actions:
public void run()
{
String head, tail, received;
do
{
// read in line from client
received = input.nextLine();
// split input line in two - head is first four
// characters for the command, tail is for rest of
// line - the text to be manipulated:
head = received.substring(0,4);
tail = received.substring(4);
// find command and choose relevant method to execute
if(head.equals("rep:"))
{
replaceText(tail);
}
else if(head.equals("app:"));
{
appendText(tail);
}
// no further tests needed - makes server ignore
// invalid commands (Add some kind of message?)
// send modified (or not) string back to client:
output.println(clientNum + ": " + text);
}while(!received.equals("QUIT"));
// close socket connection
try
{
System.out.println("Closing connection...");
client.close();
}
catch(IOException ioEx)
{
System.out.println("Unable to close connection!");
}
}
private synchronized void replaceText(String value)
{
text = value;
}
private synchronized void appendText(String value)
{
text += value;
}
}
Client:
import java.io.*;
import java.net.*;
import java.util.*;
public class SynchClient
{
public static void main(String[] args) throws IOException
{
// declare variables
InetAddress host = null;
final int PORT = 1234;
Socket socket;
Scanner networkInput, keyboard;
PrintWriter networkOutput;
// assign host address:
try
{
host = InetAddress.getLocalHost();
}
catch(UnknownHostException uhEx)
{
System.out.println("Host ID not found!");
System.exit(1);
}
// Set up socket to server and IO streams:
socket = new Socket(host, PORT);
// from server
networkInput = new Scanner(socket.getInputStream());
// to server
networkOutput =
new PrintWriter(socket.getOutputStream(),true);
// user input
keyboard = new Scanner(System.in);
String message, response;
do
{
// get user input
System.out.print("Enter message ('QUIT' to exit): ");
message = keyboard.nextLine();
// validate user input - ensure string is >= 4 chars
// long
while(message.length() < 4)
{
System.out.print("Try again: ");
message = keyboard.nextLine();
}
// send message to server:
networkOutput.println(message);
// received response from server
response = networkInput.nextLine();
// output server response
System.out.println(response);
}while(!message.equals("QUIT"));
}
}
I really cannot figure this out, and while not vitally important, I'd like to know for reference what is going wrong. So, any hints would be nice.
Dude.
else if(head.equals("app:"));
see the semicolon at the end there? :-) Remove that, and your problems should magically go away.
edited to add: The semicolon at the end of the else block terminates the condition and the code in the brackets below is thus executed every iteration of the while loop in ClientHandler2.run()