【问题标题】:jdbc cannot connect to mysql behind nat with port forwardingjdbc 无法通过端口转发连接到 nat 后面的 mysql
【发布时间】:2014-10-24 04:04:39
【问题描述】:

这个问题已经解决了。这是我检查“拒绝连接”错误所遵循的列表。

  1. MySQL 服务器状态
    • 它正在运行吗?
    • 是否禁用了 --skip-networking ?
    • 是否绑定到地址 0.0.0.0 ?
    • 该服务是否被任何防火墙阻止?
    • 它是否在其日志文件中引发任何错误/警报/警告?
  2. 客户端状态
    • 你能到达服务器ip/url吗?
    • 你能用这个端口远程登录服务器吗?
    • 可以在同一台机器上使用其他mysql客户端软件通过同一网络路由登录mysql服务吗?
    • 检查防火墙设置
    • 检查 mysql 连接器/驱动程序 !!

这个问题的答案似乎很愚蠢:我使用了一个过时的mysql驱动程序(5.1.9,当前最新版本是5.1.32)。

我仍然不知道为什么旧版本不起作用。


我在 virtualbox 托管的虚拟机中设置了一个 mysql 服务器,我可以使用命令行 mysql 客户端或 mysql 工作台在主机中成功连接到它。

但我无法使用具有相同 ip 和端口的 mysql jdbc 连接器连接到它。

我用 nat 连接了主机和 vm,端口将 mysql 服务器的 3306 转发到主机的 9936 端口。

我用来测试连接的java代码:

String url = "jdbc:mysql://127.0.0.1:9936/test";
Class.forName ("com.mysql.jdbc.Driver").newInstance();
Connection conn = DriverManager.getConnection(url, "usr", "pwd");

这是错误:

Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

这真的很奇怪,因为我可以成功地 telnet 到它并使用我能找到的任何 mysql 客户端连接到它,但是 java 代码不起作用!


2014 年 9 月 30 日更新

我尝试了以下步骤,但不起作用:

  1. 在主机和客户端计算机上禁用防火墙
  2. 将mysql服务地址绑定到0.0.0.0
  3. 确保 mysql 不会跳过网络
  4. 确保在“%”域上启用并授予连接到 mysql 的帐户

这是当前状态:

虚拟框设置:

我可以使用mysql客户端成功连接到它:

但简单的 jdbc 代码会引发错误:


添加证明:

mysql-connector-java 5.1.9:

mysql-connector-java 5.1.32:

【问题讨论】:

  • 您的连接字符串指向 127.0.0.1,通常映射到 localhost。你不应该使用VM IP地址吗?你在说什么NAT?如果虚拟机只能从 LAN 内部访问,只需将虚拟网络接口设置为 LAN 中的 IP
  • @Raffaele 根据virtualbox.org/manual/ch06.html#network_nat 我们可以从主机到达虚拟机端口 A 的唯一方法是将其端口转发到主机的端口 B。因此对主机端口 B 的请求被转发到虚拟机的端口 A . 在这种情况下,对 127.0.0.1:9936 的请求被转发到 vm 的 3306 端口。配置必须正确,因为我可以使用其他客户端连接到 mysql 服务器。
  • 查看 6.5“桥接网络”。这是一个简单的设置,只需要点击一个复选框,也许会解决你的问题
  • @Raffaele 谢谢。但是我选择使用NAT是因为主机是笔记本电脑……你知道,子网IP前缀是不断变化的。带有端口转发的 NAT 应该是最好的计划。
  • @Raffaele 问题不在于如何与虚拟机共享网络,而是为什么在 Java 代码中这个 NAT 计划不起作用。

标签: java mysql jdbc virtualbox nat


【解决方案1】:

我在 ArchLinux 虚拟机(主机是 Windows 8.1)中有 MariaDB,网络配置摘录/etc/mysql/my.cnf 如下:

#skip-networking
bind-address = 0.0.0.0

这是我的 VirtualBox NAT 配置:

我还授予了远程连接权限:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION

通过此设置,我可以使用 MySQL 客户端从主机的 9936 端口进行连接。

这是我的 gradle 构建:

apply plugin: 'java'

apply plugin: 'application'
mainClassName = "Main"

repositories {
    mavenCentral()
}

dependencies {
    runtime 'mysql:mysql-connector-java:5.1.32'
}

这是我在根包中的Main.java

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        try {
            String url = "jdbc:mysql://127.0.0.1:9936/test";
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            Connection conn = DriverManager.getConnection(url, "root", null);
            System.out.println("Connection successful!");
        } catch(Throwable t) {
            t.printStackTrace();
        }
    }
}

使用gradle run 从主机运行它会产生:

Connection successful!

您能否使用完全相同的设置重现如此成功的情况?是否允许 Java 使用网络连接(例如通过防火墙应用程序)?

【讨论】:

  • 不适合我。我们的场景之间有一些区别:1我使用ubuntu作为主机和客户端2我使用mysql服务器5.6,3我使用maven 3.1.0,也许4我使用java 8。thx都一样!
  • 我也在使用 Java 8。好的,我想到的事情是:主机或来宾上的操作系统/发行版差异或网络级别阻塞:我会排除它,因为您可以通过其他方式连接(除非 Java 使用一些特定于操作系统的网络与其他工具不同的功能);构建工具:不应该相关; Java 版本的细微差异:可能是,我使用的是 .20; MySQL 驱动程序/服务器差异:可能是,在服务器上使用 5.1.32 驱动程序和 MariaDB;主机或来宾上的应用程序级防火墙:可能是
  • Java 政策:我想他们也可以,但我不是那里的专家
  • 这个stackoverflow.com/questions/2121829/… 可能有一些额外的见解,它似乎暗示了更多的东西,比如Java MySQL 驱动程序版本(甚至是下载它的位置)是一个可能的原因。你用的是哪个版本?
  • 天啊。我将“mysql-connector-java”版本从 5.1.9 更改为 5.1.32,现在一切正常!非常感谢!!
猜你喜欢
  • 1970-01-01
  • 2012-02-23
  • 1970-01-01
  • 2011-07-01
  • 1970-01-01
  • 2018-01-21
  • 2018-07-01
  • 2022-08-08
  • 2020-02-16
相关资源
最近更新 更多