I have this small test socket connection class:-
import java.net.Socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
public class TestTelnet {
public static void main(String args[]) throws Exception {
Telnet telnet = new Telnet();
Socket socket = null ;
socket = new Socket("localhost", 23);
socket.setKeepAlive(true);
BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
System.out.println(r.readLine());
socket.close();
}
}
It works perfectly well when I use another port (for example 25 for SMTP) and the println of r.readLine works brilliantly. I can also connect to port 23 via the command prompt (telnet localhost 23) and I get the following returned:-
Ubuntu 8.10
my-laptop login:
But when I try and connect to port 23 using my java class, it just hangs on the readLine println. Does anyone know why this is?
I guess it's because your expecting a line (with CR or CRLF termination) but your telnet service does not send a complete line. Try using r.read() instead of r.readLine()
Telnet is a protocol, and is probably expecting you to do option negotiation. Once you send it something useful, it will probably send you something useful.
see: http://www.faqs.org/rfcs/rfc854.html
Telnet is both a protocol and an application
When you use telnet the application to a machine, the application sends the protocol information so the remote machine may respond.
Since you say it stay there, it means it is working, it's just you are not following the protocol.
The protocol is described here:
https://www.rfc-editor.org/rfc/rfc854
What you're trying to do here is write a telnet application.
A good example of a Telnet client can be found at http://www.java2s.com/Code/Java/Network-Protocol/ExampleofuseofTelnetClient.htm
Related
I wanted to explore an option to write minimal code to check if db2 server is running using plain java sockets. Just like doing telnet to server. It seems db2 is not configured to respond for telnet connection. Any help?
Below code works for mysql, but not working db2.
This code is equivalent to telnet ip port
Below is the java code
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class myApp {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.8.142", 50000);
String pattern = "mysql|oracle|db2";
Pattern r = Pattern.compile(pattern);
InputStream in = socket.getInputStream();
byte[] b = new byte[512];
in.read(b);
String response = new String(b);
in.close();
socket.close();
Matcher m = r.matcher(response);
System.out.println(m.find(0));
}
}
For mysql2, telnet return some characters with mysql text, version and some encoded ascii characters. But for db2, its seems like telnet is stuck without any response.
If you telnet to a Db2-server (Db2 for Linux/Unix/Windows) on the correct port, and telnet shows "Connected to" then it means that something is listening on that port on that host.
If something is listening on that port, then telnet will first display Connected to ..., and Escape character is ... . If it is a Db2-LUW server that is listening on the port, you will see nothing further (which looks like a hang). You can then abort the process.
If you do not get a connection (and get an error message) then either a firewall blocks that port, or address is incorrect, or nothing is listening on the specified port at this time.
If it is a Db2-LUW server that is listening on the port, your code should not do a read on the socket, after getting a connection, because it will hang (for as long as the TCP timeout I believe) , as would telnet.
The Db2 Knowledge Center should be the first place to look for details.
If the Db2-server participates in discovery solutions, this can help. Otherwise, connecting to the database is the way to know if a Db2-server is running. That means, apart from drivers, you need to know in advance the host/port, the authentication-mechanism, and any configured encryption, plus any relevant credential tokens/keys/certs/uid+pwd as needed for authentication.
You could also look at the Apache Derby source code, as it implements the DRDA protocol, too see if you can mimic a connection attempt.
Keep in mind that enterprises often have production Db2-servers in a high availability configuration, and often have monitoring and alerting systems that verify constantly that the Db2-server is behaving properly. So consider whether wheel re-invention is useful.
This will still not solve the problem as an tcp server can produce similar behaviour.
Right now, I made a simple server in java as so:
import Java.net.*;
import Java.io.*;
import Java.util.*;
class Server{
public static void main(String[] args){
int PORT = 13;
try(ServerSocket server = new ServerSocket(PORT)){
while(true){
try(Socket connection = server.accept()){
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString());
out.flush();
connection.close();
} catch(IOException ex){}
}
}
catch(IOException ex){
System.err.println(ex);
}
}
}
I compile and run this from the command line. Being on Port 13, I try to run this on telnet as so: telnet localhost 13 but all it gives me is "Connection to host lost". Mind you, I did this after enabling telnet on Windows 10 and installing it. Is there a simple step I'm missing?
Telnet won't connect to localhost ...
Yes it did. That's why it said 'connection to host lost' instead of 'connection refused'.
And here's what happened. You coded:
connection.close();
You got:
connection to host lost
You closed the connection; Telnet told you so.
That's what's supposed to happen.
There is no problem here to solve.
Or else you got an I/O exception in the server accept loop.
But as you are ignoring them it is impossible to say which.
In your program, following events occurs:
Server starts at 13
telnet localhost 13 : connects to that server
As soon as connection is established, server sends date
You will see date on your client
out.flush() says the client I am done writing
telnet client don't understand server command (Date)
telnet closes the connection
Telnet - Connection to host lost - on port 1099 in local machine
UPDATE #2: BLUF: I think I found the problem, but I need help figuring out how to fix it. The device needs a command with prefix and suffix STX>command ETX> (I had to drop the open bracket so stackoverflow would show it). When I send over TCP using Hercules (which works), the host interprets STX> and ETX> correctly and just displays "command", however I wrote a java client program that sends the same information but it shows up on the host as "STX>commandETX>". What is java doing differently?
Original:
I've been troubleshooting this for the last few days and I'm out of ideas so here I am. First some background information that may or may not be relevant:
I have a SICK LMS151 LIDAR sensor that I need to access through an Android application. The sensor is designed as a TCP server so you connect as a client and send the command STX>sRN LMDscandataETX>. This cues the sensor to spit a bunch of data back to the client. On a computer I can use a program like Hercules in TCP client mode, send the command and instantly receive the data without issue. However getting an Android app to do the same has been problematic (I've attached the client code below).
I wrote a server app on a separate android device which my client app has been able to connect to and exchange data. I send the command "STX>sRN LMDscandataETX>" through the connection and that's exactly how it shows up on the server side. When the server app sends data, I can see it on my client. However, when I attempt to connect to the sensor with the client, it connects but does not respond to my request for data. Any ideas of issues to look into would be helpful because at this point I'm fresh out. Thanks!
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class TcpClient extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
runTcpClient();
}
private static final int TCP_SERVER_PORT = 2111;
private void runTcpClient() {
try {
Socket s = new Socket("192.168.0.105", TCP_SERVER_PORT);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
Log.i("TcpClient", "Connected!");
//send output msg
String outMsg = "<STX>sRN LMDscandata<ETX>";
out.write(outMsg);
out.flush();
Log.i("TcpClient", "sent: " + outMsg);
//accept server response
String inMsg = in.readLine() + System.getProperty("line.separator");
Log.i("TcpClient", "received: " + inMsg);
//close connection
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UPDATE: Spent some more time on this today. Added a BoundedInputStream from Apache in hopes that maybe I wasn't seeing anything because the sensor wasn't sending a /n character at the end of each reading. Also converted from BufferedReader to Scanner. No luck. I'm fairly convinced now that it's not a problem with my client reading but instead it is somehow sending the command differently from the computer such that it isn't understood by the sensor.
Ok, I solved this issue and I think its worth sharing. After using wireshark I found that the command that worked is substituting STX> and ETX> for \u0002 and \u0003. These are standard TCP headers and footers. I manually went into my code to make the substitution and voila! It worked.
I was trying to implement a simple server program in python and client program in java.
Python server runs well. And Java client compiles good. But cannot connect to Python server.
This is my server.py
import sys
import socket
HOST = ""
PORT = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created")
try:
s.bind((HOST, PORT))
except Socket.error as msg:
print("Bind failed.")
print("Error code: "+str(msg[0]))
print("Message: "+str(msg[1]))
sys.exit()
print("Socket bind complete")
s.listen(10)
print("Socket now listening")
while 1:
conn, addr = s.accept()
print("Connected with: "+addr[0])
print(str(addr[1]))
s.close()
And this is my Client.java file:
import java.net.Socket;
import java.io.IOException;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 8888);
System.out.println("Connected");
socket.close();
System.out.println("Socket closed");
} catch(IOException exception) {
exception.printStackTrace();
}
}
}
Python server listens to Port 8888. But Java client cannot connect.
This is the output when I run Client:
java Client
And the output:
java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at Client.connect(Client.java:84)
at Client.<init>(Client.java:65)
at Client.main(Client.java:301)
Error connecting to localhost at 5555
Why can't it connect? When I write an equivalent Java server program, it works fine.
This is my Java server: Server.java
import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.io.IOException;
public class ChatServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(8888);
Socket socket = server.accept();
InetAddress ip = socket.getInetAddress();
System.out.println("Client connected: "+ip.getHostAddress());
socket.close();
} catch(IOException exception) {
exception.printStackTrace();
}
}
}
So my question is short:
Why is Client.java connected to Server.java but not Server.py?
Any help would be appreciated. Thankyou.
Seems like you never cleanly close the socket in your Python code, so it could still be stuck from a previous run attempt? Also, your python program currently doesn't do anything with the connection once received, just keeps trying to accept.
Try something like this:
while(1):
conn, addr = s.accept()
print("Connected with: "+addr[0])
#Waits for any incoming data and echoes it back
while(1):
data = conn.recv(1024)
#break if not found to get to close statement which was never reached in old code
if not data: break
print("Received data:", data.decode())
conn.sendall(data)
conn.close()
I use the exact Python code and Java code you post, it seems work fine, may be something wrong with your environment? you can diagnosis the problem with following steps(assume you run your program in a linux box like me):
1.just run the python server script
./server.py
2.use netcat to see if the server is good for connect
nc -zv localhost 8888
if things goes well, you may see connect established as expected.
if not working, use netcat to build a tcp server listen on port 8888
nc -l -p 8888
and connect to it with your java program.
you can also use netstat to distinguish if server.py works fine
sudo netstat -ntlp | grep :8888
I think I can solve your problem, but I do not know why.
You can have a try by adding an item on firewall config with
-A INPUT -i lo -j ACCEPT
then, restart your iptables service.
I've asked this question yesterday and no one was able to figure out the problem I was having. So I was hoping of providing a more up to date code with the suggestions from yesterday added on. Basically, I've been trying to form a connection between a server and a client but whenever I executed the server then the client, I'd get this exception: Address already in use. The obvious answer would be to give it a new port, but even then I still get this error. I'm assuming it has something to do with my code somewhere going wrong. Can anyone spot it please? I have attached the server class and the client class.
This is the error I get:
Exception in thread "main" java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
at java.net.ServerSocket.bind(ServerSocket.java:376)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at MessageServer.main(MessageServer.java:16)
Server code:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
public class MessageServer {
public static void main(String[] args) throws IOException {
try {
int port = 53705;
ServerSocket server = new ServerSocket(port);
while (true) {
System.out.println("Waiting for client...");
//server.setReuseAddress(true);
Socket client = server.accept();
System.out.println("Client from " + server.getInetAddress() + " connected.");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String inputLine = in.readLine();
System.out.println("Client said: '"+inputLine+"'");
Writer count = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
byte c [] = count.toString().getBytes();
count.flush();
count.close();
in.close();
}
} catch (IOException e) {
System.err.println(e);
}
}
}
Client code:
import java.net.*;
import java.io.*;
public class MessageSendClient {
public static void man(String args[]) throws IOException {
String servername = "localhost";
int port = 53705;
Socket server;
//server.setReuseAddress(true);
try {
server = new Socket (servername,port);
System.out.println("Connected to " + server.getInetAddress());
DataInputStream in = new DataInputStream(new BufferedInputStream(server.getInputStream()));
server.close();
byte c[] = new byte[100];
int num = in.read(c);
String count = new String(c);
System.out.println("Server said: " + count);
} catch (Exception e) { }
}
}
You're getting the error when the server program attempts to open up a socket on port 53705 for listening. The Address already in use message means just that, another process on your machine is already using port 53705. It could be that some daemon process has opened this same port by coincidence, or your web browser has opened this port and is still using it.
Most likely, though, is that you have another instance of your server program running somewhere in the background. Check all your terminal windows, or check your IDE for tabs containing the status of running programs.
By the way, "unique port" is a bit misleading, as port 53705 isn't "unique" in any way, it just happens to be a port number you (or somebody) picked that you hope isn't already in use. To get a truly unique port, use new ServerSocket(0) which will ask the system to allocate an unused port. To find out which port was assigned, use serverSocket.getLocalPort(). You might print it out, and then pass it to the client program as a command-line option.
I think you are running into a plattform and java liberary specific issue.
Please provide additional infos about your os plattform (x86/x64) and which version of jdk from which vendor are you using?
According to this Link
http://www.oracle.com/technetwork/java/javase/7u51-relnotes-2085002.html
Above Oracle JDK 7u51: The default socket permissions assigned to all code including untrusted code have been changed. You can only bind sockets to the ephemeral port range on each system.
Port 53705 should be a save ephemeral port.
But still use
netstat -an | grep 53705
to double check if the port is used in linux and use netstat or tcpview for windows.
You can use
less /proc/sys/net/ipv4/ip_local_port_range
for linux to check your ephemeral port range for linux and find
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
in windows to get determine your ephemeral port range. More about ephemeral range in windows can be found in how to change/view ephemeral port range in windows machines
I can confirm your server code and client without the "man" -> "main" typo is running under Opensuse 12.3 with
Java version "1.7.0_51"
OpenJDK Runtime Environment (IcedTea 2.4.4) (suse-8.32.5-i386)
OpenJDK Client VM (build 24.45-b08, mixed mode)
jvm is running by an non admin user with groups: www,dialout,video,shadow,users
I tested your code and it works correctly (meaning: I can connect to the server, didn't test the rest). Just pay attention to the main method in MessageSendClient, there's a typo ("man" instead of "main") and the correct signature is:
public static void main(String[] args)
not
public static void main(String args[]) // Still compatible but not recommended (C-like syntax)
Make sure the listening port is free by executing (replace YOUR_PORT with the number)
netstat -tulpn | grep :YOUR_PORT
because that's the reason why you get that exception. If you're on Windows you might just run
netstat -an
and search for the port.