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.
Related
So I am working on a software that will monitor(and may alter by acting as a Forrowder) all the DNS requests made by my router.
What I did?
So for first I wrote a Java code that can listens to a specific port and prints all the requests to the console[For now I just want to test with the requests].
The code is:
import java.net.*;
import java.io.*;
public class PortLogger{
public static void main(String[] args) {
LoggerServer loggerServer = new LoggerServer(53);
loggerServer.start();
}
}
class LoggerServer extends Thread{
private int port;
public LoggerServer(int port){
this.port = port;
}
#Override
public void run(){
try{
int id = 1;
ServerSocket server = new ServerSocket(port);
System.out.println("Server Listening at port " + port);
Socket client;
while(true){
client = server.accept();
ClientHandler clientHandler = new ClientHandler(client, id++);
clientHandler.start();
}
}catch(Exception ex){
System.out.println("Exception at Server : 1 :: EX = " + ex);
}
}
}
class ClientHandler extends Thread{
private Socket client;
private int id;
public ClientHandler(Socket client, int id){
this.client = client;
this.id = id;
}
#Override
public void run(){
try {
String data = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
while(true){
data = reader.readLine();
if(data.length() > 0){
System.out.println("Client : " + id + " :: " + data);
}
}
}catch(Exception ex){
System.out.println("Exception at Client : " + id + " :: EX = " + ex);
}
}
}
The sole propose of this code for now is to Show me all the requests made to the server.
I know that I also have to change the DNS Server in my router for this.
So, for that I first tried by going to internet setup and put the local IP of my computer as DNS server.
But it was showing :
DNS IP and LAN IP must be on different networks!
But I found another way to do it.
It is as follows:
I went to the setup wizard of the router and the set the DNS Server to the same IP.
Surprisingly this worked!
[I have no idea whether this is a bug in the D-Link Firmware or not.
I have also added an exception to allow all request both inbound and outbound to port 53.
What is the problem?
So now the problem is that even after successfully changing the DNS to my servers. There seemed to be no requests at all to the console. I tried a lot but nothing.
I checked that the program was working fine by voluntarily sending request to it using telnet?
Now am I doing anything wrong or there is some bug with the router(its is a old one).
NOTE: The black lines on the images are just to hide my public IP address nothing special.
EDIT: I tried a few more times then found that websites were not opening when I changed the DNS in my router but still nothing in the console!
While it is difficult to give you a complete answer why your application doesn't work I can suggest some ways to investigate:
Port 53 is a privileged port. This means on Linux binding to that port requires root privileges and the application will throw an exception due to 'permission denied' if executed as a 'normal' user. As you are using Windows I don't know what it does if you try to bind as a 'normal' user, or you might be executing as an Admin user (or whatever the equivalent of 'root' is in Windows) and you don't know it. It might even just silently fail i.e. appear to bind when in fact it hasn't and no data is passed through you your application. As an aside, defaulting to 'root' as the default execution user in Linux is not the norm because it's insecure and most Linux distributions if not all do not allow this by default i.e. you can have this but you have to tell the distribution this is what you intend during installation. I'll let you come to your own conclusions what stance Windows takes for making users 'admin'...
In a scenario such as this if it were me I would immediately go to some networking tools to see what is happening. On Linux this is tcpdump or Wireshark. You can also get Wireshark for Windows as it's a GUI application. This will let you monitor and filter network traffic and so will be independent of your application. You can filter by source or destination address and/or port number.
I would leave the DNS setting alone in the router and change the DNS settings in one machine first, call it the test client, and set its DNS address to the machine where your application is running. Using tcpdump or Wireshark you can then make requests on your test_client e.g. browser requests and see the resulting network traffic.
You never mentioned if after changing your router's DNS settings all browser requests from clients fail. This is what I would expect to see if your router can no longer get a name resolution. However there maybe some DNS caching going on in your clients so you may appear to get successful DNS requests on your test_client. Again look at network traffic or use a Linux client which will provide you with much better networking tools.
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.
I need to make a server and client that connects to the server.
Problem: "the server works. the client can only connect to localhost, it cannot connect to a server on the internet. I want the client to connect to the server, via a public ip-address that the server is hosted on."
First of all, I have made sure that the port is forwarded and reachable i have tested the port, secondly i have disabled firewall completely from the server machine.
below is the test code i am using:
The Server: nothing fancy just simple - terminates if a client is connected, else just awaits a connection.
public class Server {
public static void main(String args[]) {
try {
ServerSocket srvr = new ServerSocket(52000);
srvr.accept();
}
catch(Exception e) {
e.printStackTrace();
}
}
}
The Client: I have used no-ip.com to mask the ip of the server to "biogenserver2.noip.me".
Using .getCanonicalHostName(); will return the ip.
public class Client {
public static void main(String args[]) {
try {
String ip = Inet4Address.getByName("somets.noip.com").getCanonicalHostName();
InetSocketAddress sa = new InetSocketAddress(ip, 52000);
//Socket skt = new Socket("0.0.0.0", 52000); //local - this works fine.
Socket skt = new Socket();
skt.connect(sa);
}
catch(Exception e) {
e.printStackTrace();
}
}
}
When i run this the server connects fine, but the client returns a "connection timeout" exception
Any help will be appreciated. Thanks.
Answer:
"Just for clarity: You have checked the port is open via public IP as returned by no-ip and the server will quit without exception when you run that little testclient (on a machine that is not the server machine) - is that correct?" – Fildor
TL:DR
Don't run the client and server on the same machine and the same network trying to connect to your server through your public ip then to your own local network will result in a client timeout exception
I was running the client and server on the same machine and also the same network. This caused the client timeout exception. I tried running the Client on a different machine and a different network and i was able to connect successfully.
What version of IP protocol your application uses? On linux, you may figure it out with netstat -tunap | grep 52000 and watching whether first field is tcp or tcp6. If latter, then it is possible that problem with IPv6 connectivity exists and you may want to prefer using IPv4 to IPv6 by specifying -Djava.net.preferIPv4Stack=true to JVM.
I have 1 machine, which i pinged using below scripts
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
class SimplePing
{
static void connectAndPing(String host, int port, int loop, int pingLoop, int socketTimeout){
if(loop>0){
SocketAddress sAdress;
Socket kkSocket;
for(int i=0;i<loop;i++){
sAdress = new InetSocketAddress(host, port);
for(int j=0;j<pingLoop;j++){
try {
kkSocket = new Socket();
kkSocket.connect(sAdress, socketTimeout);
kkSocket.close();
Thread.sleep(1000L);
} catch (Exception e) {
System.out.println(e);
}
System.out.print("!");
}
}
}
}
public static void main(String[] args)
{
String host = args[0];
int port = Integer.parseInt(args[1]);
int socketTimeout = Integer.parseInt(args[2]);
int loop = 100000;
int pingLoop = 100;
System.out.println("Begin ping. . .");
connectAndPing(host, port, loop, pingLoop, socketTimeout);
System.out.println("End ping. . .");
}
}
It gave me result like (don't bother the mark, its just my comment)
Then i tried to ping using UNIX ping tools, and get
This is the remote machine info:
**SunOS msgbkrpapp18 5.10 Generic_138888-03 sun4v sparc SUNW,SPARC-Enterprise-T5120
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)**
Why do i get different result? which one is more valid?
Port 8000 is being used by my messaging apps, which accepting connection from external IP, my client complained that the apps is down sometimes, he read the system health by using the above java program.
If i checked in apps side, no abnormal condition met, even the threadpool for connection didn't even meet the max value.
Any suggestion??
Thank you
The answer is in your code:
int socketTimeout = 1000;
...
kkSocket.connect(sAdress, socketTimeout);
The other side didn't respond in 1 second, so you get a SocketTimeoutException. Try to increase the timeout. Also have code to handle the exception - like increasing a counter for unaswered pings.
After a few days, we managed to find the culprit, it turn out, the somaxconn attributes in OS level, still in default value (128), considering our massive burst, we suggest client to configure the number into 1000;
Now, the amount of refused connection dropped 98.15%, for example, we could get almost 400 times refused connections in 1 day, now, it could drop to 6 - 9 per days.
While we are still working to give optimal tuning configuration, i would like to say thanks you to all of you for giving me some suggestions :)
Thanks
The both results are valid, the difference is that Unix ping does not need to connect to specific port of the server. And it looks that your app simply does not send any response within the given timeout.
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