I am trying to prototype TCP hole punching of a NAT as described in this paper http://www.brynosaurus.com/pub/net/p2pnat/.
I have this simple piece of code that tries to open a connection to a server on a specific local port. I am trying to observe on the public server if the NAT maps both the connections to the same NAT mapping.
int localPort = getFreeLocalPort();
while (true) {
Socket connection = new Socket(_publicServerHost,_publicServerPort,
getLocalSocketAddress(), localPort);
connection.setReuseAddress(true);
connection.close();
}
The 1st time it connects fine. But the 2nd attempt it throws an exception:
Local port chosen for hole punching: 65416
2012-06-17 15:55:21,545 ERROR - Address already in use: connect
2012-06-17 15:55:25,175 DEBUG - Details:
java.net.BindException: Address already in use: connect
at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.6.0_24]
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351) ~[na:1.6.0_24]
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213) ~[na:1.6.0_24]
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200) ~[na:1.6.0_24]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366) ~[na:1.6.0_24]
at java.net.Socket.connect(Socket.java:529) ~[na:1.6.0_24]
at java.net.Socket.connect(Socket.java:478) ~[na:1.6.0_24]
at java.net.Socket.(Socket.java:375) ~[na:1.6.0_24]
at java.net.Socket.(Socket.java:249) ~[na:1.6.0_24]
try adding connection.setSoLinger(true, 0); directly before connection.close();.
Like so:
connection.setSoLinger(true, 0);
connection.close();
This forces the OS to release the socket.
On what basis was the local port chosen? Obviosuly not a sound one. You would be better off letting the system choose it, by specifying zero, and getting the actual value from the socket after opening, if you need it at all.
Have you solved your problem ?
setReuseAddress() should be called before port is assigned.
Socket connection = new Socket();
connection.setReuseAddress(true);
connection.bind( ...);
Related
I saw a lot of "java.net.ConnectException: Connection refused" questions but none referring to timeout of this error. My problem is I have to connect to a server that, in some cases, is blocked (connected by another software to the same port). So, I'm doing a loop with some max retries to try to connect:
My current code (of course, is depending on a lot of configurations for my software, but is working fine):
public TCPConnector(TCPDefinition tcpDefinition) throws IAException {
ivTcpDefinition = tcpDefinition;
// Initialize the socket
boolean retry = false;
int counter = 1;
do {
try {
ivSocket = new Socket();
ivSocket.connect(new InetSocketAddress(tcpDefinition.getHostname(), tcpDefinition.getPort()), tcpDefinition.getConnectTimeOut());
ivSocket.setSoTimeout(tcpDefinition.getAckTimeOut());
retry = false;
}
catch (UnknownHostException uhe) {
throw new IAException(null, new StringBuffer("Can't find host: ").append(tcpDefinition.getHostname()).toString(), uhe);
}
catch (SocketException see) {
StringBuilder sb = new StringBuilder("Connection refused to host ").append(tcpDefinition.getHostname()).
append(" port ").append(tcpDefinition.getPort()).append(". Connection Attempt Nr. ").append(counter);
logger.error(sb.toString(), see);
retry = true;
if (counter++ > tcpDefinition.getConnectRetries())
throw new IAException(null, sb.toString(), see);
else
logger.error("will retry to connect");
}
catch (IOException ioe) {
StringBuilder sb = new StringBuilder("I/O error while connecting to host ").append(tcpDefinition.getHostname()).
append(" port ").append(tcpDefinition.getPort()).append(". Connection Attempt Nr. ").append(counter);
logger.error(sb.toString(), ioe);
retry = true;
if (counter++ > tcpDefinition.getConnectRetries())
throw new IAException(null, sb.toString(), ioe);
else
logger.error("will retry to connect");
}
}
while (retry);
}
Well, the problem is this:
On Windows, every second, the SocketException is thrown, instead the IOException, while I have configured a timeout of 5000 msec to ivSocket.connect
On Linux, this is thrown every millisecond!!
Windows:
2019-12-05 12:40:47,609 ERROR DefaultQuartzScheduler_Worker-1 TCPConnector - Connection refused to host localhost port 13002. Connection Attempt Nr. 1
java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
2019-12-05 12:40:48,703 ERROR DefaultQuartzScheduler_Worker-1 TCPConnector - Connection refused to host localhost port 13002. Connection Attempt Nr. 2
java.net.ConnectException: Connection refused: connect
Linux:
2019-12-05 12:45:47,609 ERROR DefaultQuartzScheduler_Worker-1 TCPConnector - Connection refused to host localhost port 13002. Connection Attempt Nr. 1
java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
2019-12-05 12:45:47,610 ERROR DefaultQuartzScheduler_Worker-1 TCPConnector - Connection refused to host localhost port 13002. Connection Attempt Nr. 2
java.net.ConnectException: Connection refused: connect
Why the timeout is not executed? Well this is not exactly right. If I configure a timeout less than 1 second on Windows, then the timeout is executed. 500 msec:
2019-12-05 11:47:07,375 ERROR DefaultQuartzScheduler_Worker-1 TCPConnector - I/O error while connecting to host localhost port 13002. Connection Attempt Nr. 1
java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
2019-12-05 11:47:07,875 ERROR DefaultQuartzScheduler_Worker-1 TCPConnector - I/O error while connecting to host localhost port 13002. Connection Attempt Nr. 2
java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
It is possible to configure a "connect refuse" timeout?
There is no such thing as a "connection refused timeout".
"Connection refused" happens when the server sees the connection request, but there is no service listening for connections on the IP + port that the request is directed to. The server then "refuses" the connection. This typically happens instantly, so so no timeout is triggered.
"Connection timed out" happens (typically) when something stops the connection request from reaching the server1, 2. So the client-side will wait for the response from the server, and then resend / wait a few times. And eventually the time allotted for establishing a connection will expire ... and the connection times out.
As you can see these are different scenarios. And they are reported back to the Java client-side differently.
So the reason you are not getting timeouts is that the "connection refused" responses are coming back quick enough that your configured timeout is not exceeded.
That might also explain why setting the connect timeout small might have changed the behavior. There may also be issues with the granularity of the timeout that the OS allows Java to set.
To investigate this further, I think we would need a minimal reproducible example. For example, we need to see how you have implemented the code that manages the server-socket and accepts connections on the server side.
1 - The blockage could be on the server's reply packets.
2 - There are various possible causes for this kind of thing. The most likely are a firewall blocking traffic somewhere, a network routing problem, or using a private IP address on the wrong network.
I have orace 11g running on 192.168.1.217 and I am trying to connect it using JDBC driver with java and it gives me following error
IO Error: The Network Adapter could not establish the connection
Library I am using is ojdbc6.jar
Here is my code
public void makeOracleConnection() {
try {
Class.forName("oracle.jdbc.OracleDriver");
oraCon = DriverManager.getConnection("jdbc:oracle:thin:#192.168.1.217:1521:orcl", "hr", "hr");
oraStmt = oraCon.createStatement();
oraRsStmt=oraCon.createStatement(ResultSet.CONCUR_READ_ONLY,ResultSet.TYPE_SCROLL_INSENSITIVE);
} catch (Exception e) {
System.out.println("Error while making connection with Database : " + e.getMessage());
}
}
I have also tried to ping on 192.168.1.217 then pins is successful.
Also TNSLISTENER is running on that machine.
please help.
Please find print stack trace here
run:
java.sql.SQLRecoverableException: IO Error: The Network Adapter could not establish the connection
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:743)
at oracle.jdbc.driver.PhysicalConnection.connect(PhysicalConnection.java:657)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:560)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
at test.oracle.makeOracleConnection(oracle.java:30)
at test.oracle.<init>(oracle.java:21)
at test.oracle.main(oracle.java:69)
Caused by: oracle.net.ns.NetException: The Network Adapter could not establish the connection
at oracle.net.nt.ConnStrategy.execute(ConnStrategy.java:470)
at oracle.net.resolver.AddrResolution.resolveAndExecute(AddrResolution.java:506)
at oracle.net.ns.NSProtocol.establishConnection(NSProtocol.java:595)
at oracle.net.ns.NSProtocol.connect(NSProtocol.java:230)
at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:1452)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:496)
... 8 more
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at oracle.net.nt.TcpNTAdapter.connect(TcpNTAdapter.java:163)
at oracle.net.nt.ConnOption.connect(ConnOption.java:159)
at oracle.net.nt.ConnStrategy.execute(ConnStrategy.java:428)
... 13 more
BUILD SUCCESSFUL (total time: 1 second)
You get the error
java.net.ConnectException: Connection refused: connect
Which means that there is nothing listening on the machine and port you are trying to connect to. Your Java code looks correct so I would continue to investigate that Oracle is actually listening on port 1521 on 192.168.1.217.
If you run run netstat -n on the server you should find a line that looks like
TCP [::]:1521 [::]:0 LISTENING
If something really is listening on that port. If you do not find that line, check your Oracle configuration.
Try to connect with some other tool, ie sqlplus to verify that the issue is not with Oracle. If you cannot connect with sqlplus/sql developer, make sure that your oracle is configured to allow remote connections, and also listens on given addresses/ports
public void makeOracleConnection() {
try {
Class.forName("oracle.jdbc.OracleDriver");
Connection oraCon = DriverManager.getConnection("jdbc:oracle:thin:#192.168.1.217:1521:orcl", "hr", "hr");
Statement oraStmt = oraCon.createStatement();
//oraRsStmt=oraCon.createStatement(ResultSet.CONCUR_READ_ONLY,ResultSet.TYPE_SCROLL_INSENSITIVE);
ResultSet rs = oraStmt.executeQuery("select hello as result from dual");
while(rs.next()) {
System.out.println(rs.getString("result"));
}
}
catch (Exception e)
System.out.println("Error while making connection with Database : " + e.getMessage());
}
}
Try this out. Hope it'll help. I also don't like your connection path. Is it right? I think it should be something like this:
jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS_LIST=(LOAD_BALANCE=YES)(ADDRESS=(PROTOCOL=tcp)(HOST=ip adres)(PORT=port)))(CONNECT_DATA=(SERVICE_NAME = orcl)))","username","password"
I've tried to used RMI, here is server side. at first it worked without any exception, but now after three times whenever i try to run the below code, i will get some errors
The code is:
import java.rmi.server.UnicastRemoteObject;
/**
* Created by elyas on 12/11/14 AD.
*/
public class LogicImplement extends UnicastRemoteObject implements Logic
{
public LogicImplement() throws Exception
{
java.rmi.registry.LocateRegistry.createRegistry(6060);
java.rmi.Naming.rebind("Object1",this);
}
#Override
public int sum(int a, int b) throws Exception
{
int result = a + b;
System.out.println("ana sum executed");
return result;
}
public static void main(String[] args)
{
try
{
LogicImplement logicImplement = new LogicImplement();
} catch (Exception e)
{
e.printStackTrace();
}
}
}
The error is like this: i've tried to change the Object1 to for example Object2, but again i will get error, also i change the port number...
what is solution?
java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:341)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
at java.rmi.Naming.rebind(Naming.java:177)
at LogicImplement.<init>(LogicImplement.java:12)
at LogicImplement.main(LogicImplement.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:147)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
... 12 more
java.net.ConnectException: Connection refused
There could be couple of reasons for this exception:
You have not started your rmiregistry in background.
You are trying to connect to the wrong port number.
Your firewall maybe blocking the connections.
The Answer was very simple, By default, the registry runs on port 1099. To start the registry on a different port, specify the port number on the command line. Do not forget to unset your CLASSPATH environment variable. for more information check this link: Running the Example Programs
** So for fixing this code i must change the port number form 6060 to 1099
notice that: if 1099 is used by other services you have to test 1100, and if 1100 is used too, you have yo use 1101 and so on. :-)
Since this was a port number issue, there is another way to start the registry on the port number you want:
java.rmi.registry.Registry rmiRegistry = java.rmi.registry.LocateRegistry.
createRegistry(6060); // Creates a registry on 6060
rmiRegistry.rebind("Object1",this); // Binds to registry created on 6060
You haven't started the RMI Registry.
When you get past this, if it still happens when calling the remote method, see item A.1 of the RMI FAQ.
I am connecting to LDAP, which is working fine. However, I need to change the value of one attribute. I am able to read the current value, but I can't modify the value. This is my code:
I have tried many things from the internet, but all cause in one error:
[Root exception is java.net.ConnectException: Connection refused: connect] (It's always in the "executing" line of code).
at com.sun.jndi.ldap.LdapReferralContext.<init>(LdapReferralContext.java:74)
at com.sun.jndi.ldap.LdapReferralException.getReferralContext(LdapReferralException.java:132)
at com.sun.jndi.ldap.LdapCtx.c_bind(LdapCtx.java:410)
at com.sun.jndi.ldap.LdapCtx.c_bind(LdapCtx.java:357)
at com.sun.jndi.toolkit.ctx.ComponentContext.p_bind(ComponentContext.java:596)
at com.sun.jndi.toolkit.ctx.PartialCompositeContext.bind(PartialCompositeContext.java:183)
at com.sun.jndi.toolkit.ctx.PartialCompositeContext.bind(PartialCompositeContext.java:173)
at javax.naming.InitialContext.bind(InitialContext.java:400)
at Client.connect(Client.java:80)
at Main.main(Main.java:22)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:529)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:570)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.<init>(SSLSocketImpl.java:371)
at com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.jndi.ldap.Connection.createSocket(Connection.java:316)
at com.sun.jndi.ldap.Connection.<init>(Connection.java:186)
at com.sun.jndi.ldap.LdapClient.<init>(LdapClient.java:116)
at com.sun.jndi.ldap.LdapClient.getInstance(LdapClient.java:1580)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2678)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:296)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:134)
at com.sun.jndi.url.ldap.ldapURLContextFactory.getObjectInstance(ldapURLContextFactory.java:35)
at javax.naming.spi.NamingManager.getURLObject(NamingManager.java:584)
at javax.naming.spi.NamingManager.processURL(NamingManager.java:364)
at javax.naming.spi.NamingManager.processURLAddrs(NamingManager.java:344)
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:316)
at com.sun.jndi.ldap.LdapReferralContext.<init>(LdapReferralContext.java:93)
This is what I tried - what am I doing wrong? Please give me some suggestions.
Attribute mod0 = new BasicAttribute("attribute", "AAA");
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0);
authContext.modifyAttributes("correctDn", mods);
Later, I tried this one:
Attribute acl = new BasicAttribute( "attribute", "asdf");
authContext.modify( entryDN, new LDAPModification(LDAPModification.ADD, acl));
EDITED This is a connection refusal while processing a referral. You are talking to an LDAP slave that has sent you a referral to the master, and you can't connect to the master, either because the slave configuration has given you the wrong referral information or because there is a firewall in the way of the master LDAP server.
I'm developing a Java EE 6 application that uses AD to help with logging in. My authenticator is simple and looks like this:
#Singleton
#TransactionManagement(TransactionManagementType.BEAN)
public class ADAuthenticator{
private static final String ldapHost = "ldap://domainname.mycompany.com:389";
private static final String domain = "domainname";
public ADAuthenticator() {
}
public void authenticate(String user, String pass) throws NamingException{
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapHost);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, user + "#" + domain);
env.put(Context.SECURITY_CREDENTIALS, pass);
LdapContext ctxGC = new InitialLdapContext(env, null);
}
}
This has worked well for some time, but lately I'm getting the following exception (except some times where it magically works):
javax.naming.CommunicationException: mydomain.mycompany.com:389 [Root exception is java.net.ConnectException: Connection timed out: connect]
at com.sun.jndi.ldap.Connection.<init>(Connection.java:210)
at com.sun.jndi.ldap.LdapClient.<init>(LdapClient.java:118)
at com.sun.jndi.ldap.LdapClient.getInstance(LdapClient.java:1580)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2652)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:293)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:134)
at com.xdin.competence.util.ADAuthenticator.authenticate(ADAuthenticator.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at <ejb stuff omitted>
Caused by: java.net.ConnectException: Connection timed out: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:529)
at java.net.Socket.connect(Socket.java:478)
at java.net.Socket.<init>(Socket.java:375)
at java.net.Socket.<init>(Socket.java:189)
at com.sun.jndi.ldap.Connection.createSocket(Connection.java:352)
at com.sun.jndi.ldap.Connection.<init>(Connection.java:187)
... 101 more
Nothing has changed with the code, and according to IT-support, no configuration regarding AD has been changed either.
I seperated the relevant code into a simple console application, and it works perfectly with the exact same settings. So the problem seems related to Java EE or the webserver. Any ideas?
The packets for the TCP/IP connection do not arrive in time. This may have multiple reasons, but from what you describe, this may simply be a network congestion between your Java code and the LDAP server which in turn causes package loss. There might also be a firewall blocking that port inbetween.
You need to learn about the ping, traceroute and telnet host port tools to troubleshoot your network layer. I would suggest you team up with a network guy from IT-support and ask him nicely to help finding out where your package loss is.