Openshift java.net.SocketException: разрешение отклонено

Я использую Java8 и имею Чат-сервер, который отлично работает на моем локальном хосте, но когда я развертываю его на сервере OpenShift, я получаю следующую ошибку:

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)

Я просмотрел руководство для веб-сокетов OpenShift здесь, в котором говорится, что нужно использовать порт 8000. Но я все еще получаю ошибку.

В Openshift я запускаю свой чат-сервер на картридже WildFly Application Server 10.

Любые рекомендации оценены.

Вот мой код:

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();
        }
    }
}

В эта ссылка OpenShift говорит о привязке к порту и прокси. Я все это не понимаю. Похоже, я должен использовать порт 8000 (это я), но я не понимаю, какое имя хоста я должен использовать. Я использую имя своего приложения (jbosswildfly-easyjobs.rhcloud.com). Это правильно?

Если я изменил адрес на, http://jbosswildfly-easyjobs.rhcloud.com (т.е. префикс http://), я получаю следующую ошибку:

java.net.SocketException: неразрешенный адрес

введите описание изображения здесь

Ответ 1

В связанном сообщении в блоге говорится, что вы можете подключаться к websockets на OpenShift с помощью портов 8000 и 8443. Однако сам сервер должен быть привязан только к порту 8080, а затем вы можете подключаться извне к ws выше. Эта диаграмма, которую вы уже нашли, объясняет конфигурацию.

WildFly уже использует 8080, поэтому вы можете использовать DIY-картридж для развертывания вашего приложения (не забудьте отключить значение по умолчанию рубиновый сервер в стартовом действии, запущенном на 8080) или вдохнуть здесь.

Ответ 2

Я пытался найти решение. У меня есть некоторые решения. Все предлагают добавить -Djava.net.preferIPv4Stack=true в параметры виртуальной машины.

Atlassian Documentation также получила первопричину и решение, приведенные ниже:

Причина

  • Это одна из известных проблем с Java 7, по этот пост.
  • Это также может быть вызвано любым антивирусным или брандмауэром установленных на сервере.

Разрешение

  • Используйте свойство системы -Djava.net.preferIPv4Stack=true JVM, чтобы помочь включить поддержку IPv4 на Java 7.
  • Убедитесь, что на сервере нет антивирусного и брандмауэра блокировка Возможность штамповки для подключения к почтовому серверу.

Это решение для Java 7, но вы используете Java 8. Итак, я просматриваю ваш стек. Существует строка

 at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:125)

Что говорит, что вы используете netty.

Но netty имеет некоторое требование на основе версии. Существуют также некоторые ограничения.

JDK 5 (Netty 3.x) или 6 (Netty 4.x) достаточно. Некоторые компоненты, такие как У HTTP/2 может быть больше требований

Требования к Netty 4.x(ссылка)

Java в настоящее время не поддерживает ALPN или NPN (там является проблемой отслеживания, так что продолжайте ее!). Из-за отсутствия поддержки в JDK нам необходимо используйте Jetty-ALPN (или Jetty-NPN, если на Java < 8) bootclasspath расширение для OpenJDK.. Для этого добавьте параметр JVM Xbootclasspath ссылаясь на путь к банке Jetty alpn-boot.

java -Xbootclasspath/p:/path/to/jetty/alpn/extension.jar ...

Обратите внимание, что вы должны использовать выпуск баннера Jetty-ALPNк используемой вами версии Java.

JDK Ciphers

Java 7 не поддерживает рекомендуемые варианты шифрования по HTTP2 RFC. Чтобы решить эту проблему, мы предлагаем серверам использовать Java 8, где возможно или использовать альтернативную реализацию JCE, такую ​​как Bouncy Замок. Если это нецелесообразно, можно использовать другие шифров, но вы должны убедиться, что услуги, которые вы намереваетесь вызывать также поддерживают эти шифры, запрещенные HTTP/2 RFC, и имеют оценил риски безопасности при этом.

Включение ALPN или NPN

SslContextBuilder имеет сеттер для ApplicationProtocolConfig, который используется для настройки ALPN или NPN. См. HTTP/2 примеры для ALPN и Примеры SPDY для NPN использование.

Подробнее см. эту ссылку.

Предложения:

Итак, проверьте свою сетевую версию и примите решение в соответствии с вышеуказанными проблемами. Или используйте JDK 7, если это возможно.