【问题标题】:how to use android retrofit2 with nodejs server?如何将 android retrofit2 与 nodejs 服务器一起使用?
【发布时间】:2020-06-19 02:52:37
【问题描述】:

我正在使用 retrofit2 和 nodejs 服务器进行开发。当我在 android 中调用节点服务器时,会显示 android 的日志。 请求立即结束。这个地址的结果是正确的。当我去这个地址时,json 结果显示正确。但在 android 中我无法与节点服务器通信 android 客户端。如您所见,尽管我将超时设置为 1 分钟,但我收到了错误消息。我不知道为什么我无法与服务器通信。有人知道吗?在nodejs中,它没有显示任何日志。

安卓日志

D/OkHttp: --> GET http://192.168.0.xx:5000/api/customers
    --> END GET

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.haii.schedulemanager, PID: 8169
    java.net.SocketTimeoutException: failed to connect to /192.168.0.xx (port 5000) from /192.0.0.x (port 39078) after 60000ms
        at libcore.io.IoBridge.connectErrno(IoBridge.java:185)
        at libcore.io.IoBridge.connect(IoBridge.java:129)
        at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:137)
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
        at java.net.Socket.connect(Socket.java:621)
        at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.kt:57)
        at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:266)
        at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:180)
        at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:238)
        at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:111)
        at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:79)
        at okhttp3.internal.connection.Transmitter.newExchange$okhttp(Transmitter.kt:163)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:35)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:82)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:84)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:71)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:219)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:194)
        at okhttp3.RealCall$AsyncCall.run(RealCall.kt:138)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

清单

        android:usesCleartextTraffic="true" //this is for http

nodejs

app.get('/api/customers',(req,res)=>{

    let today = moment(new Date()).format("YYYY-MM-DD");
    let date="";

    if(moment().day()===0){
        date = getWeekday(moment(new Date()).add('days',7).format("YYYY-MM-DD"),"Saturday");
    }else{
        date = getWeekday(today,"Saturday");
    }


    let sql = "select * from customer "+
            "where isDeleted=0 and createdDate between '"+today+"' and '"+ date+"'"; 
    const params = ""
    console.log(sql);

    connection.query(
        sql,params,
        (err,rows,fields)=>{
            console.log(rows);
            res.send(rows);
        }
    )
});

ps:当我使用模拟器将 url 更改为http://10.0.2.2:5000/ 运行时,结果是正确的。但是当我在手机上运行它时,它会显示上述错误。

应用模块

    @JvmStatic
    @Singleton
    @Provides
    fun provideTaskNetwork() : ScheduleNetwork {
        return Retrofit.Builder()
            .baseUrl("http://192.168.0.xx:5000/")
            .addConverterFactory(GsonConverterFactory.create())
            .client(provideOkhttp())
            .build()
            .create(ScheduleNetwork::class.java)

界面


interface ScheduleNetwork {

    @GET("api/customers")
    fun getCustomers(

    ): Call<CustomerItem>

}

【问题讨论】:

  • 您的手机和服务器都在同一个网络上吧?请同时显示您的ip,也不会显示任何登录节点,因为phone 未与服务器通信,请同时显示您的base_url 和GET 请求interface
  • 我的手机ip是192.0.0.5(数据网络不是wifi),我的桌面是192.168.0.35。这是不同的网络。
  • 你不能在不同的网络上使用localhost,你的设备和桌面应该在同一个网络上
  • 所以我将 localohst 更改为 192.168.0.xx 。 localhost 到真实网络地址。
  • 192.162.x.x 是private IPs

标签: android node.js network-programming ip-address private-network


【解决方案1】:

您在评论中提到您的 Android 不在本地 wifi 上,而是您使用的是运营商数据网络。你不能那样做™。如果您想连接到本地网络上的测试服务器,您的 Android 必须在同一网络的 Wifi 上。如果您想使用 Android 的运营商数据网络进行连接,您的服务器必须位于公共网络地址上。

在您的 Java 回溯中,这是重要的一行。

java.net.SocketTimeoutException: 60000 毫秒后无法从 /192.0.0.x(端口 39078)连接到 /192.168.0.xx(端口 5000)

让我们阅读这一行以了解详细信息。

  1. SocketTimeoutException。此 Java 代码在等待连接到服务器后放弃了。

  2. to /192.168.0.xxx (port 5000) 此代码尝试连接到运行在本地专用网络上的机器上的服务器 192.168.0.xxx 的端口 5000。您可能打算将其用作您的 nodejs 服务器。我们知道这是一个专用网络,因为所有地址192.168.x.y 都是专用网络地址。所有地址10.x.y.z 也是如此。我的专用网络和您的专用网络可能具有完全相同的地址。因此,公共网络从不尝试处理发往这些专用网络的流量。它只是忽略它。

  3. from /192.0.0.xxx (port 39078) 你的本地机器,你的机器人,试图发起连接。它的地址是您运营商网络上的192.0.0.xxx。您的运营商网络检测到您正在尝试连接到 192.168.x.y 专用网络地址。公共网络根本不允许这样做,因此您的运营商会忽略它。

  4. after 60 000ms Android 上的 Java 代码在一分钟后就放弃了。当网络忽略流量时会发生超时。

【讨论】:

  • 谢谢兄弟,我解决了这个理解私有/公共网络的问题。
猜你喜欢
  • 2018-06-02
  • 1970-01-01
  • 2018-10-28
  • 2020-09-28
  • 2016-01-18
  • 2014-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多