问题
I am using Java8 and have a Chat Server that works perfectly on my localhost, but when I deploy it to an OpenShift server, I get the following error:
java.net.SocketException: Permission denied
2016-09-05 10:36:11,300 INFO [stdout] (Thread-125) Starting Chat server on localhost:8000 ... 2016-09-05 10:36:13,194 ERROR [stderr] (Thread-125) Exception in thread "Thread-125" java.net.SocketException: Permission denied 2016-09-05 10:36:13,194 ERROR [stderr] (Thread-125) at sun.nio.ch.Net.bind0(Native Method) 2016-09-05 10:36:13,195 ERROR [stderr] (Thread-125) at sun.nio.ch.Net.bind(Net.java:433) 2016-09-05 10:36:13,195 ERROR [stderr] (Thread-125) at sun.nio.ch.Net.bind(Net.java:425) 2016-09-05 10:36:13,195 ERROR [stderr] (Thread-125) at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223) 2016-09-05 10:36:13,195 ERROR [stderr] (Thread-125) at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74) 2016-09-05 10:36:13,196 ERROR [stderr] (Thread-125) at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:125) 2016-09-05 10:36:13,196 ERROR [stderr] (Thread-125) at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:476) 2016-09-05 10:36:13,196 ERROR [stderr] (Thread-125) at io.netty.channel.DefaultChannelPipeline$HeadHandler.bind(DefaultChannelPipeline.java:1000) 2016-09-05 10:36:13,196 ERROR [stderr] (Thread-125) at io.netty.channel.DefaultChannelHandlerContext.invokeBind(DefaultChannelHandlerContext.java:463) 2016-09-05 10:36:13,197 ERROR [stderr] (Thread-125) at io.netty.channel.DefaultChannelHandlerContext.bind(DefaultChannelHandlerContext.java:448) 2016-09-05 10:36:13,197 ERROR [stderr] (Thread-125) at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:842) 2016-09-05 10:36:13,197 ERROR [stderr] (Thread-125) at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:195) 2016-09-05 10:36:13,197 ERROR [stderr] (Thread-125) at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:338) 2016-09-05 10:36:13,198 ERROR [stderr] (Thread-125) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:370) 2016-09-05 10:36:13,198 ERROR [stderr] (Thread-125) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:353) 2016-09-05 10:36:13,198 ERROR [stderr] (Thread-125) at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) 2016-09-05 10:36:13,198 ERROR [stderr] (Thread-125) at java.lang.Thread.run(Thread.java:745)
I have looked at the OpenShift web sockets guide here, which says port 8000 should be used. But I still get the error.
On Openshift I am running my chat server on a WildFly Application Server 10 cartridge.
Any advise appreciated.
Here is my code:
WebAppInitializer.java
try {
new Thread() {
public void run() {
com.jobs.spring.chat.Server chatServer = new com.jobs.spring.chat.Server();
chatServer.startServer();
}
}.start();
} catch (Exception e) {
e.printStackTrace();
}
Server.java
import java.net.Socket;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* https://blog.openshift.com/paas-websockets/
* @author Richard
*
*/
public class Server {
//private static final String SERVER = "localhost";
private static final String SERVER = "jbosswildfly-easyjobs.rhcloud.com";
private static final Integer PORT = 8000;
public static void main(String[] args) {
startServer();
}
public static void startServer() {
Configuration config = new Configuration();
config.setHostname(SERVER);
config.setPort(PORT);
final SocketIOServer server = new SocketIOServer(config);
server.addConnectListener(new ConnectListener() {
@Override
public void onConnect(SocketIOClient client) {
System.out.println("onConnected");
client.sendEvent("chat_message:message", new Message("Welcome to the chat!"));
}
});
server.addDisconnectListener(new DisconnectListener() {
@Override
public void onDisconnect(SocketIOClient client) {
System.out.println("onDisconnected");
}
});
server.addEventListener("chat_message:send", String.class, new DataListener<String>() {
@Override
public void onData(SocketIOClient client, String data, AckRequest ackSender) throws Exception {
Message message = null;
try {
message = new ObjectMapper().readValue(data.toString(), Message.class);
} catch (Exception e) {
e.printStackTrace();
}
message.setDate(System.currentTimeMillis());
server.getBroadcastOperations().sendEvent("chat_message:message", message);
}
});
System.out.println("Starting Chat server on " + SERVER + ":" + PORT+" ...");
server.start();
System.out.println("Chat server started");
System.out.println("Chat server Environment Info: " + System.getenv());
try {
Socket socket = new Socket(SERVER, PORT);
printSocketInformation(socket);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Prints debug output (to stdout) for the given Java Socket.
*/
public static void printSocketInformation(Socket socket) {
try {
System.out.format("Port: %s\n", socket.getPort());
System.out.format("Canonical Host Name: %s\n", socket.getInetAddress().getCanonicalHostName());
System.out.format("Host Address: %s\n\n", socket.getInetAddress().getHostAddress());
System.out.format("Local Address: %s\n", socket.getLocalAddress());
System.out.format("Local Port: %s\n", socket.getLocalPort());
System.out.format("Local Socket Address: %s\n\n", socket.getLocalSocketAddress());
System.out.format("Receive Buffer Size: %s\n", socket.getReceiveBufferSize());
System.out.format("Send Buffer Size: %s\n\n", socket.getSendBufferSize());
System.out.format("Keep-Alive: %s\n", socket.getKeepAlive());
System.out.format("SO Timeout: %s\n", socket.getSoTimeout());
} catch (Exception e) {
e.printStackTrace();
}
}
}
In this link OpenShift talk about port binding and proxies. I don't really understand all of it. It looks like I should use port 8000 (which I am), but I am not clear what hostname I should use. I am using my application url name (jbosswildfly-easyjobs.rhcloud.com). Is that correct?
If I change the address to, http://jbosswildfly-easyjobs.rhcloud.com
(i.e. prefix http://
) I get the following error:
java.net.SocketException: Unresolved address
回答1:
The linked blog post says that you can connect to websockets on OpenShift using ports 8000 and 8443. However, the server itself needs to be bound only to port 8080 and then you can connect externally to the ws ports above. This diagram that you have already found explains the configuration.
WildFly is using 8080 already, so you may want to use the DIY cartridge to deploy your app (don't forget to disable the default ruby server in the start action hook that is running on 8080) or be inspired here.
回答2:
I was trying to find out solution. I have got some solutions. All are suggesting to add -Djava.net.preferIPv4Stack=true
to the VM options.
Atlassian Documentation also got the root cause and solution given below:
Cause
- This is one of the known issues with Java 7, as per this post.
- This can also be caused by any anti-virus or firewall software installed on the server.
Resolution
- Use the
-Djava.net.preferIPv4Stack=true
JVM system property to help enable support for IPv4 on Java 7.- Check that anti-virus and firewall software on the server is not blocking Stash's ability to connect to the mail server.
This solution is for Java 7, but you are using Java 8. So I lookup your stacktrace. There is a line
at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:125)
Which is telling that you are using netty.
But netty has some requirement on version basis. There is also some limitations.
JDK 5 (Netty 3.x) or 6 (Netty 4.x) is enough. Some components such as HTTP/2 might have more requirements
Requirements for Netty 4.x(link)
Java does not currently support ALPN or NPN (there is a tracking issue so go upvote it!). For lack of support in the JDK we need to use the Jetty-ALPN (or Jetty-NPN if on Java < 8) bootclasspath extension for OpenJDK. To do this, add a Xbootclasspath JVM option referencing the path to the Jetty alpn-boot jar.
java -Xbootclasspath/p:/path/to/jetty/alpn/extension.jar ...
Note that you must use the release of the Jetty-ALPN jar specific to the version of Java you are using.
JDK Ciphers
Java 7 does not support the cipher suites recommended by the HTTP2 RFC. To address this we suggest servers use Java 8 where possible or use an alternative JCE implementation such as Bouncy Castle. If this is not practical it is possible to use other ciphers but you need to ensure that the services you intend to call also support these ciphers forbidden by the HTTP/2 RFC and have evaluated the security risks of doing so.
Enabling ALPN or NPN
The SslContextBuilder has a setter for an ApplicationProtocolConfig which is used to configure ALPN or NPN. See the HTTP/2 examples for ALPN and SPDY examples for NPN usage.
For details description, you can go through this link.
Suggestions:
So check your netty version and take decision according above issues. Or use JDK 7 if possible.
来源:https://stackoverflow.com/questions/39266277/openshift-java-net-socketexception-permission-denied