使用网络服务发现在 Java 服务器和 Android 客户端之间进行通信

2024-01-01

我正在构建一个 Java 服务器应用程序(在 PC 上运行),它使用以下命令将自身注册到本地网络JmDNS http://jmdns.sourceforge.net/,以及一个 Android 客户端应用程序,该应用程序应该使用以下命令发现 java 服务器网络服务发现 http://developer.android.com/training/connect-devices-wirelessly/nsd.html.
当我先运行android应用程序,然后运行java服务器时,应用程序成功发现注册的java服务器。
But当我第一次运行服务器然后运行Android应用程序时,onDiscoveryStarted调用的方法但是onServiceFound方法从未触发 - Android 应用程序未发现服务器。 在我看来,这是一种意想不到的行为。

成功案例:
安卓应用程序日志:
08-24 22:42:06.157 NSD_DISCOVER onCreate
08-24 22:42:06.373 NSD_DISCOVER: onDiscoveryStarted 服务发现已启动
08-24 22:42:30.256 NSD_DISCOVER: onServiceFound 已知服务类型:_http._tcp。
08-24 22:42:30.293 NSD_DISCOVER: onServiceResolved 解析成功。名称:NsdApp,类型:._http._tcp,主机:/10.0.0.2,端口:52288

Java服务器日志:
START
挂号的
END
WAITING_FOR_MESSAGE
你好世界
END_THREAD

失败案例:

安卓应用程序日志:
08-24 22:05:21.690 NSD_DISCOVER: onCreate
08-24 22:05:21.908 NSD_DISCOVER: onDiscoveryStarted 服务发现已启动

Java服务器日志:
START
挂号的
END
WAITING_FOR_MESSAGE

服务器代码

public class Server {

    public static String mServiceName = "NsdApp";
    public static final String SERVICE_TYPE = "_http._tcp.local";

    static ServerSocket mServerSocket;


    public static void main(String[] args) throws IOException {

        System.out.println("START");

    try {
        mServerSocket = new ServerSocket(0);
    } catch (IOException e) {
        System.out.println("ServerSocket(0) FAILED");
    }

    int mPort = mServerSocket.getLocalPort();

    JmDNS jmdns = JmDNS.create();
    ServiceInfo info = ServiceInfo.create(SERVICE_TYPE, mServiceName, mPort, "B");
    jmdns.registerService(info);

    System.out.println("REGISTERED");

    jmdns.close();

    Thread mReceiveMessage = new Thread(new ReceiveMessage());
    mReceiveMessage.start();

    System.out.println("END");
}

public static class ReceiveMessage implements Runnable {

    public void run() {
        System.out.println("WAITING_FOR_MESSAGE");
        try {

            Socket clientSocket = mServerSocket.accept(); 
            InputStreamReader inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 
            String message = bufferedReader.readLine();
            System.out.println(message);

            bufferedReader.close();
            inputStreamReader.close();
            clientSocket.close();
            System.out.println("END_THREAD");

        } catch (IOException ex) {
            System.out.println("Problem in message reading");
        }
    }
}
}

客户端代码

public class MainActivity extends Activity {

public static final String TAG = "NSD_DISCOVER";
public static final String SERVICE_TYPE = "_http._tcp.";
NsdManager.DiscoveryListener mDiscoveryListener;
NsdManager.ResolveListener mResolveListener;
NsdManager mNsdManager;
int port;
InetAddress host;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Log.v(TAG, "onCreate");

    mNsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);
    initializeResolveListener();
    initializeDiscoveryListener();
    mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}


public void initializeDiscoveryListener() {
    mDiscoveryListener = new NsdManager.DiscoveryListener() {

        @Override
        public void onDiscoveryStarted(String regType) {
            Log.v(TAG, "onDiscoveryStarted Service discovery started");
        }

        @Override
        public void onServiceFound(NsdServiceInfo service) {
            if (!service.getServiceType().equals(SERVICE_TYPE)) {
                Log.v(TAG, "onServiceFound Unknown Service Type: " + service.getServiceType());
            } else {
                Log.v(TAG, "onServiceFound Known Service Type: " + service.getServiceType());
                mNsdManager.resolveService(service, mResolveListener);
            }
        }

        @Override
        public void onServiceLost(NsdServiceInfo service) {
            Log.e(TAG, "service lost" + service);
        }

        @Override
        public void onDiscoveryStopped(String serviceType) {
            Log.i(TAG, "Discovery stopped: " + serviceType);
        }

        @Override
        public void onStartDiscoveryFailed(String serviceType, int errorCode) {
            Log.e(TAG, "Discovery failed: Error code:" + errorCode);
            mNsdManager.stopServiceDiscovery(this);
        }

        @Override
        public void onStopDiscoveryFailed(String serviceType, int errorCode) {
            Log.e(TAG, "Discovery failed: Error code:" + errorCode);
            mNsdManager.stopServiceDiscovery(this);
        }
    };
}


public void initializeResolveListener() {
    mResolveListener = new NsdManager.ResolveListener() {

        @Override
        public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
            Log.e(TAG, "onResolveFailed Resolve failed" + errorCode);
        }

        @Override
        public void onServiceResolved(NsdServiceInfo serviceInfo) {
            Log.v(TAG, "onServiceResolved Resolve Succeeded. " + serviceInfo);
            port = serviceInfo.getPort();
            host = serviceInfo.getHost();

            SendMessage sendMessageTask = new SendMessage();
            sendMessageTask.execute();
        }
    };
}


private class SendMessage extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {
        try {

            Socket client;
            PrintWriter printwriter;

            client = new Socket(host, port); 
            printwriter = new PrintWriter(client.getOutputStream(), true);
            printwriter.write("hello world"); 

            printwriter.flush();
            printwriter.close();
            client.close(); 

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

}


你正在呼唤jmdns.close()注册后。只有当您打开 jmdns 时,您的服务才能被发现。您应该删除该调用close, 做你的jmdns变量是您的类的成员,然后仅当您不希望您的服务再被发现时才调用 close 。另外,这是一个很好的调用形式unregisterAllServices()在关闭 jmdns 之前。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用网络服务发现在 Java 服务器和 Android 客户端之间进行通信 的相关文章

  • 在 Spring 中设置 WS https 调用超时 (HttpsUrlConnectionMessageSender)

    我正在尝试为 WS 调用设置超时 我延长了WebServiceGatewaySupport并尝试将发送者超时设置为如下 public Object marshalSendAndReceive Object requestPayload We
  • LibGdx 如何使用 OrthographicCamera 滚动?

    我已经找了 10 个小时 字面意思 我已经完成了 我需要问一下 事情是我正在学习如何使用 LibGdx 来编写 Java 游戏 我正在做一个水平太空飞船游戏 所以 我最糟糕的问题是我不知道如何滚动 我认为绘制会更好地解释 我想绘制一个巨大的
  • CheckedTextView 的中心文本和复选标记

    我实现的布局如下图所示 我使用的代码是
  • Vertx HttpClient getNow 不工作

    我的 vertx HttpClient 有问题 下面的代码显示使用 vertx 和纯 java 测试 GET Vertx vertx Vertx vertx HttpClientOptions options new HttpClientO
  • android:widgetLayout 和 android:layout 之间的区别?

    我得到一些奇怪的配置 其中 widgetLayout 配置列表项的内部空间 而布局配置整个项目列表和屏幕背景 有人能真正解释一下什么是 widgetLayout 吗 android layout 整个首选项的布局 包括标题 摘要和小部件 a
  • Android 设备 ID(不是 IMEI)

    我使用命令 adb devices 列出连接的设备 在我的电脑上我得到 附加设备列表 HT9CTP820988 器件 我的问题是 如何以编程方式获取此 id HT9CTP820988 你所看到的adb devices命令是序列号 序列号 创
  • android studio logcat 中字母的含义是什么? [复制]

    这个问题在这里已经有答案了 在 android studio 中运行应用程序时 会生成 logcat 并且每行的开头都有字母 这些字母的含义是什么 这些字母表用于各种日志选项 请参阅此链接 日志选项 https developer andr
  • Android - 从服务器获取响应时验证 JSON 以避免 JSONException

    在我的一些与服务器通信并使用 http 获取响应的应用程序中 我使用 json 来格式化数据服务器端 当它到达设备时 我使用类似于我在 stackoverflow 上找到的代码 private class LoadData extends
  • Android Lollipop BLE 扫描 - 获取没有重复的外设

    Android Lollipop 引入了一种扫描 BLE 外设的新方法 通过蓝牙扫描仪 http developer android com reference android bluetooth le BluetoothLeScanner
  • 使用 IntelliJ / Android Studio 调试基于 gradle 的单元测试

    我正在使用robolectric gradle 插件 https github com robolectric robolectric gradle plugin为 Android 编写单元测试 到目前为止 除了能够使用 Android S
  • Android - 如何合并两个视频

    基本上 我正在寻找一种将两个 mp4 视频文件 在 SD 卡上 组合在一起的方法 更像是在第一个视频的末尾附加第二个视频 我进行了很多搜索 但找不到合适的解决方案 好吧 我根本找不到任何解决方案 所以我的问题是 是否有一个库可以组合 并可能
  • 如何在高速缓存中存储图像

    我对此完全空白 我想从 URL 下载图像 并且必须将其存储在内部 以便下次我不需要连接到网络 而是从缓存中检索它 但我不知道该怎么做 谁能帮我提供一个代码片段 import java io BufferedInputStream impor
  • 用 Java 创建迷宫求解算法

    我被分配了用 Java 创建迷宫求解器的任务 这是任务 Write an application that finds a path through a maze The maze should be read from a file A
  • 将字符串中的字符向左移动

    我是 Stack Overflow 的新手 有一道编程课的实验室问题一直困扰着我 该问题要求我们将字符串 s 的元素向左移动 k 次 例如 如果输入是 Hello World 和3 它将输出 lo WorldHel 对于非常大的 k 值 它
  • Android 在通话期间播放音频文件[重复]

    这个问题在这里已经有答案了 对于我的 Android 应用程序 我想在从应用程序接听电话后播放音频文件 应用程序将发起电话呼叫 一旦接收者接听电话 应用程序应开始播放录制的音频文件 通过在谷歌上进行大量搜索 我发现这对于未root的设备来说
  • Android 中的字符串加密

    我正在使用代码进行加密和加密 它没有给出字符串结果 字节数组未转换为字符串 我几乎尝试了所有方法将字节数组转换为字符 但没有给出结果 public class EncryptionTest extends Activity EditText
  • Java SE + Spring Data + Hibernate

    我正在尝试使用 Spring Data Hibernate 启动 Java SE 应用程序 并且到目前为止已经完成了以下操作 配置文件 Configuration PropertySource classpath hibernate pro
  • 使用 Android 的 Mobile Vision API 扫描二维码

    我跟着这个tutorial http code tutsplus com tutorials reading qr codes using the mobile vision api cms 24680关于如何构建可以扫描二维码的 Andr
  • 如何在Java中跨类共享变量,我尝试了静态不起作用

    类 Testclass1 有一个变量 有一些执行会改变变量的值 现在在同一个包中有类 Testclass2 我将如何访问 Testclass2 中变量的更新值 由 Testclass1 更新 试过这个没用 注意 Testclass1和Tes
  • 从 Android 中的过渡动画中排除 BottomNavigation

    我一直在四处寻找 但找不到有助于解决这个特定问题的答案 我的应用程序有一个自定义滑入 滑出效果 如下所示 Intent intent new Intent getApplicationContext MyActivity class sta

随机推荐

  • 如何使用 NSAttributedString 在 Swift 中添加图像作为文本附件?

    我正在尝试使用我作为按钮放入的图像为 iOS 构建一个自定义键盘 当我按下按钮时 链接到该按钮的图像将被放入属性字符串中 该字符串将加载到自定义键盘视图内的 UiTextView 中 那是有效的 问题是 当我将新图像附加到属性字符串时 字符
  • Excel 2010、VBA 和 ListObjects 小计未随表更改而更新

    因此 具有以下结构 从 A1 开始 显示片段 gt 运行 table border color BBB border width 0px 0px 1px 1px border style dotted body font 12px Aria
  • do 块内的 Haskell where 子句语法

    我正在尝试重构mapM a 内的函数调用doHaskell 中的块 我想将 lambda 提取到 本地 命名函数以使代码更具可读性 我的代码最初看起来像这样 do mapM x gt x 1 aList return aValue 我想把它
  • FFMPEG H264 压缩预设会影响视频质量吗? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我绝对不是 FFMPEG 专家 但根据这个文件 http ffmpeg org trac ffmpeg wiki x264EncodingGuide
  • 遮罩图像,从多个渐变创建矩形

    我有一个径向渐变用作mask image将图像 淡入 background color behind图片 mask image radial gradient ellipse at center rgba 255 255 255 1 1 r
  • 如何使用 javascript 创建 xhtml 元素

    如何使用 javascript 动态创建 html 元素 我想在表格单元格内添加一个复选框 所以我希望代码看起来像这样 td td
  • 将 GraphQL 数据拉入 gatsby-browser.js (或更好的解决方案,请)

    我正在尝试运行一个GraphQL里面查询replaceRouterComponent从内部gatsby browser js 盖茨比浏览器API https www gatsbyjs org docs browser apis 然而 我可以
  • 什么是特殊目的寄存器? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 什么是特殊用途寄存器 特殊用途寄存器的名称是什么 以及每个寄存器的一些描述 顾名思义 特殊用途寄存器是专为任务而设计的寄存器 例如 c
  • Dart 支持参数化单元测试吗?

    我想运行一个 Dart 测试 该测试使用一组输入和预期输出重复进行 类似于 JUnit 的情况 我编写了以下测试来实现类似的行为 但问题是 如果所有测试输出计算不正确 则测试只会失败一次 import package test test d
  • Flask 应用程序使用 opencv 运行速度非常慢

    我有一个烧瓶应用程序 它从相机读取帧并将其传输到网站 相机 py from threading import Thread from copy import deepcopy import queue import cv2 class Ca
  • 为什么我不能用 std::unordered_map 替换 std::map

    这个问题可能有点粗略 因为我家里没有可用的代码 但我知道这件事否则会困扰我整个周末 当我尝试将一些代码更新到 C 11 时 我开始替换一些代码std map with std unordered map 该代码仅使用std map find
  • CGRectContainsRect 不工作

    我用这个方法有问题 我有两个显然彼此包含的矩形 我什至手动绘制了它们的坐标以确保 当我使用 CGRectContainsRect 比较这两个矩形时 它返回 false 对于我的一生 我已经尝试了一切 搜索了网络 但我找不到这个问题的答案 有
  • 使用 jQuery 从 HTML 文本查询脚本元素

    我正在通过以下方式加载页面 ajax 并插入parts将结果放入页面的相应部分 ajax url whole page html success function data status xhr result xhr responseTex
  • Jenkins:将用户定义的变量传递给 Email-Ext 插件

    我使用 Email Ext 插件在声明性管道的构建后阶段的构建结束时发送结果电子邮件 在电子邮件正文中 我尝试插入一些环境变量和一些用户定义的环境变量 内置变量显示正常 但是我定义的任何用户定义变量在电子邮件正文中都是空的 或者在 Atta
  • Visual Studio 2017 中的 React 项目

    我想在 Visual Studio 2017 中与我的 NET 应用程序一起开发 React 应用程序 在同一解决方案中 我正在使用 TypeScript 所以我想要一个可以自定义构建的项目类型 我想对项目进行 webpack 等 所以标准
  • Swing 组件不显示泰文字符

    我有一个简单的摆动应用程序 当我将泰语文本设置为 JLabel 或其他组件时 它们显示像问号的字符而不是泰语文本 有什么办法可以在 Swing 应用程序中支持泰语吗 没有特殊的功能或配置要做 确保您的字体支持泰语字符 当我遇到同样的问题时
  • 如何在 BaseColumns 中使用 _COUNT

    我一直在读BaseColumns https developer android com reference android provider BaseColumns html https developer android com ref
  • 在辅助屏幕上显示 NSWindow

    我想显示一个NSWindow在辅助监视器上全屏显示情节提要中创建的 以下代码导致窗口显示在主屏幕 主屏幕上 Y 原点没问题 但 X 原点是 0 它应该是 1680 下面的代码在优胜美地之前有效 NSScreen screen NSScree
  • RxAndroid 3主线程

    我正在尝试在 Rx3 中找到 subscribeOn 的主线程 Single just getHeavyData subscribeOn Schedulers io observeOn AndroidSchedulers mainThrea
  • 使用网络服务发现在 Java 服务器和 Android 客户端之间进行通信

    我正在构建一个 Java 服务器应用程序 在 PC 上运行 它使用以下命令将自身注册到本地网络JmDNS http jmdns sourceforge net 以及一个 Android 客户端应用程序 该应用程序应该使用以下命令发现 jav