访问docker主机时java.net.SocketException(java.net.SocketException when accessing docker host)

650 IT屋

I'm new to docker and need to connect from inside a running centos docker container to the host running the container using a java socket. When trying to connect a SocketException occurs:

[root@743fedf46128 test]# java SocketTest 10.1.196.134 4444 127.0.0.1 0
Trying to connect using ip address
Using remote ip 10.1.196.134
Using remote port 4444
Using local ip 127.0.0.1
Using local port 0
/10.1.196.134, 4444, /127.0.0.1, 0
    java.net.SocketException: Invalid argument or cannot assign requested address
    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 SocketTest.main(SocketTest.java:54)

The Java Class TestSocket actually only tries to open a socket:

    public static void main(String[] args) {
    String remoteIp = args[0];
    String remotePort = args[1];
    String localIp = args[2];
    String localPort = args[3];


    System.out.println("Trying to connect using ip address");
    System.out.println("Using remote ip " + remoteIp);
    System.out.println("Using remote port " + remotePort);
    System.out.println("Using local ip " + localIp);
    System.out.println("Using local port " + localPort);

    Socket workSocket = null;
    try {
        InetAddress remoteAddress = InetAddress.getByName(remoteIp);
        InetAddress localAddress = InetAddress.getByName(localIp);
        int rPort = Integer.parseInt(remotePort);
        int lPort = Integer.parseInt(localPort);
        System.out.println(remoteAddress + ", " + rPort + ", " + localAddress + ", " + lPort);
        workSocket = new Socket();
        workSocket.setReuseAddress(true);
        workSocket.bind(new InetSocketAddress(localAddress, lPort));
        workSocket.setSoTimeout(1000);
        workSocket.connect(new InetSocketAddress(remoteAddress, rPort));
    }

And it fails on the last line (the connect).

Ping as well as telneting the port from within the running container however work:

[admin@pluto ~]$ docker exec -it --user root pensive_almeida bash
[root@743fedf46128 test]# ping -c 3 10.1.196.134
PING 10.1.196.134 (10.1.196.134) 56(84) bytes of data.
64 bytes from 10.1.196.134: icmp_seq=1 ttl=64 time=0.047 ms
64 bytes from 10.1.196.134: icmp_seq=2 ttl=64 time=0.101 ms
64 bytes from 10.1.196.134: icmp_seq=3 ttl=64 time=0.099 ms

--- 10.1.196.134 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.047/0.082/0.101/0.026 ms

[root@743fedf46128 test]# telnet 10.1.196.134 4444
Trying 10.1.196.134...
Connected to 10.1.196.134.
Escape character is '^]'.
This is a test
Connection closed by foreign host.

Can anybody provide me a hint, why trying to connect fails with java ? For completness, my Dockerfile looks like this:

FROM centos:centos7

# Set the proxies
ENV HTTP_PROXY 'http://175.23.236.88:3128/'
ENV HTTPS_PROXY 'http://175.23.236.88:3128/'

# Install telnet
RUN yum -y install telnet
RUN yum -y install wget

# Prepare environment
ENV JAVA_HOME /opt/java
ENV PATH $PATH:$JAVA_HOME/bin

# Install Oracle Java7
RUN wget --no-check-certificate --no-cookies --header "Cookie:oraclelicense=accept-securebackup-cookie" \
        http://download.oracle.com/otn-pub/java/jdk/7u80-b15/jdk-7u80-linux-x64.tar.gz && \
        tar -xvf jdk-7u80-linux-x64.tar.gz && \
        rm jdk*.tar.gz && \
        mv jdk* ${JAVA_HOME}

WORKDIR /opt/test

# Add the test class
ADD dockerfiles/SocketTest.class /opt/test/SocketTest.class

Thank you in advance for your replies.

解决方案

You could add --net=host to your docker run command, but in that way the host has full access to your container. You can however expose a port within your Dockerfile or on the outside in your docker run command, but I prefer the former.

Here's an example of mine:

Pull base image

FROM ubuntu:14.04

RUN apt-get update RUN apt-get install software-properties-common -y RUN add-apt-repository ppa:webupd8team/java -y RUN apt-get update RUN echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections RUN apt-get install oracle-java8-installer -y RUN apt-get install oracle-java8-set-default -y RUN mkdir /temporary ADD Client.jar /temporary

WORKDIR /temporary

EXPOSE 15000

ENTRYPOINT /bin/bash

我很接近Docker,需要使用一个java套接字从一个正在运行的centos docker容器的内部连接到运行该容器的主机。当尝试连接一个SocketException时发生:



  [root @ 743fedf46128 test]#java SocketTest 10.1.196.134 4444 127.0.0.1 0 
尝试使用ip地址连接
使用远程ip 10.1.196.134
使用远程端口4444
使用本地ip 127.0.0.1
使用本地端口0
/ 10.1.196.134,4444,/127.0.0.1,0
java.net.SocketException:无效的参数或无法分配请求的地址
在java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
在java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
在java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java: 182)
在java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
在java.net.Socket.connect(Socket.java:579)
在java.net.Socket .connect(Socket.java:528)
在SocketTest.main(SocketTest.java:54)
< / code>


Java Class TestSocket实际上只尝试打开套接字:



  public static void main(String [] args){
String remoteIp = args [0];
String remotePort = args [1];
String localIp = args [2];
String localPort = args [3];


System.out.println("尝试使用ip地址连接");
System.out.println("使用远程ip"+ remoteIp);
System.out.println("使用远程端口"+ remotePort);
System.out.println("using local ip"+ localIp);
System.out.println("使用本地端口"+ localPort);

Socket workSocket = null;
try {
InetAddress remoteAddress = InetAddress.getByName(remoteIp);
InetAddress localAddress = InetAddress.getByName(localIp);
int rPort = Integer.parseInt(remotePort);
int lPort = Integer.parseInt(localPort);
System.out.println(remoteAddress +","+ rPort +","+ localAddress +","+ lPort);
workSocket = new Socket();
workSocket.setReuseAddress(true);
workSocket.bind(new InetSocketAddress(localAddress,lPort));
workSocket.setSoTimeout(1000);
workSocket.connect(new InetSocketAddress(remoteAddress,rPort));
}


最后一行(连接)失败。



Ping,以及从正在运行的容器中的端口号,但是工作:



  [admin @ pluto〜] $ docker exec -it --user root pensive_almeida bash 
[root @ 743fedf46128 test]#ping -c 3 10.1.196.134
PING 10.1.196.134(10.1.196.134)56( 84)字节的数据。
从10.1.196.134的64字节:icmp_seq = 1 ttl = 64时间= 0.047 ms
从10.1.196.134的64个字节:icmp_seq = 2 ttl = 64时间= 0.101 ms
从10.1 .196.134:icmp_seq = 3 ttl = 64 time = 0.099 ms

--- 10.1.196.134 ping统计---
3个数据包发送,3个接收,0%丢包,时间1999ms
rtt min / avg / max / mdev = 0.047 / 0.082 / 0.101 / 0.026 ms

[root @ 743fedf46128 test]#telnet 10.1.196.134 4444
尝试10.1.196.134。 ..
连接到10.1.196.134。
转义字符为'^]。
这是一个测试
外部主机关闭的连接。


任何人都可以提供一个提示,为什么尝试连接失败与java?
对于完整性,我的Dockerfile如下所示:



  FROM centos:centos7 

#设置代理
ENV HTTP_PROXY'http://175.23.236.88:3128/'
ENV HTTPS_PROXY'http://175.23.236.88:3128/'

#安装telnet
运行yum -y安装telnet
运行yum -y安装wget

#准备环境
ENV JAVA_HOME / opt / java
ENV PATH $ PATH: $ JAVA_HOME / bin

#安装Oracle Java7
RUN wget --no-check-certificate --no-cookies --header"Cookie:oraclelicense = accept-securebackup-cookie"\
http://download.oracle.com/otn-pub/java/jdk/7u80-b15/jdk-7u80-linux-x64.tar.gz&& \
tar -xvf jdk-7u80-linux-x64.tar.gz&& \
rm jdk * .tar.gz&& \
mv jdk * $ {JAVA_HOME}

WORKDIR / opt / test

#添加测试类
ADD dockerfiles / SocketTest.class / opt / test / SocketTest.class


提前感谢您的回复。


解决方案

您可以将--net = host添加到docker运行命令中,但主机可以完全访问您的容器。然而,您可以在Docker文件中或在docker运行命令中的外部暴露一个端口,但我更喜欢前者。



以下是我的示例:





拉基本图片



FROM ubuntu:14.04



运行apt-get update
运行apt-get安装软件属性常用-y
RUN add-apt-repository ppa:webupd8team / java -y
运行apt-get update
RUN echo debconf shared / accepted-oracle-license-v1-1 select true | debconf-set-choices
运行apt-get install oracle-java8-installer -y
运行apt-get install oracle-java8-set-default -y
运行mkdir / temporary
ADD Client.jar / temporary



WORKDIR / temporary



EXPOSE 15000



ENTRYPOINT / bin / bash


本文地址:IT屋 » 访问docker主机时java.net.SocketException