【问题标题】:Network connection to (external) Python server与(外部)Python 服务器的网络连接
【发布时间】:2018-08-17 03:35:05
【问题描述】:

我创建了一个 Java 客户端,它应该连接到一个 python 服务器。作为一个独立的,它工作得非常好,连接已建立,数据将通过。

public class ClientTest {

    public static void main(String args[]) {
        requestGazeData();
    }

    public static void requestGazeData() {
        ZMQ.Context context = ZMQ.context(1);
        ZMQ.Socket request = context.socket(ZMQ.REQ);
        request.connect("tcp://xxx.x.x.x:50020");

        // Ask for the sub port
        request.send("SUB_PORT");
        String subPort = request.recvStr();
        System.out.println("subPort: " + subPort);

        // open a sub port to listen to pupil
        ZMQ.Socket subscriber = context.socket(ZMQ.SUB);
        subscriber.connect("tcp://xxx.x.x.x:" + subPort);

        String gaze = "gaze";
        subscriber.subscribe(gaze.getBytes(Charset.forName("UTF-8")));

        while (true) {
            String msg = subscriber.recvStr();
            System.out.println(msg);

            subscriber.close();
            context.term();
        }
    }
}

现在这个客户端必须在应用程序启动后运行,但没有任何反应。我没有从服务器获得任何数据并且它卡住了。这绝对是Android方面的问题,我认为尤其是活动类。这个看起来如下:

public class MainActivity extends Activity {

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

        // Set function for button
        findViewById(R.id.button).setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ClientTest.requestGazeData();
                    }
                });

    }
}

我也没有例外。在我的Manifest.xml 中,我输入了所有需要的权限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>

最后,我允许在我的防火墙中的端口上进行连接(在 Ubuntu 中通过 ufw)。我已经没有想法如何修复它并使其工作。

更新: 由于一个可能的答案,我尝试了AsyncTask,但仍然发生任何事情。这是我更新的活动课程:

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set function for the button
        findViewById(R.id.connectButton).setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        new NetworkCall().execute("");
                    }
                });
    }

    private class NetworkCall extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            ZMQ.Context context = ZMQ.context(1);
            ZMQ.Socket request = context.socket(ZMQ.REQ);
            request.connect("tcp://xxx.x.x.x:50020");

            System.out.println("Connected");
            // ask for the sub port
            request.send("SUB_PORT");
            String subPort = request.recvStr();
            System.out.println("subPort: " + subPort);

            //int subPortNo = Integer.parseInt(subPort);

            // open a sub port to listen to pupil
            ZMQ.Socket subscriber = context.socket(ZMQ.SUB);
            subscriber.connect("tcp://xxx.x.x.x:" + subPort);

            String gaze = "gaze";
            subscriber.subscribe(gaze.getBytes(Charset.forName("UTF-8")));

            while (true) {
                String msg = subscriber.recvStr();
                System.out.println(msg);

                //subscriber.close();
                //context.term();
            }
        }

        @Override
        protected void onPostExecute(String result) {
            System.out.println("DONE");
        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        //getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

【问题讨论】:

  • 代码安全三点:[A] 最好始终在 REQ 上将 LINGER 设置为 1 在实例化时立即进行套接字(以避免在 .term() 上无限挂断的风险),接下来,[B] .close() 在收到端口# 和 [C] 避免阻塞 subscriber.revStr() 而是在 Poller.poll() 中实现非阻塞处理。几乎可以肯定 Android 系统确实会讨厌任何(可能是无限的)阻塞方法。

标签: java android python sockets network-programming


【解决方案1】:

您不能在 Android 的主线程中调用进行网络通信的函数。您需要将此任务传递给AsyncTask,它会正常工作。

这是一个AsyncTask 的示例,它可能会对您有所帮助。

private class NetworkCall extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {
        Data data = ClientTest.requestGazeData();
        return data.toString();
    }

    @Override
    protected void onPostExecute(String result) {
        // Do something with your data.toString();
    }

    @Override
    protected void onPreExecute() {}

    @Override
    protected void onProgressUpdate(Void... values) {}
}

现在只需点击您的button 即可启动AsyncTask

findViewById(R.id.button).setOnClickListener(
    new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new NetworkCall().execute("");
        }
    });

【讨论】:

  • 我编辑了我的代码并添加了AsyncTask,但不幸的是你的解决方案没有帮助。
  • 请您更新您的问题以及您现在拥有的代码。这样我就可以检查那里是否有任何错误的实现。
  • 更新了我的问题。
【解决方案2】:

所以在尝试了一切之后,我禁用了防火墙,最后连接正常了。有时它可能是小细节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-09
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2018-04-18
    • 2017-09-26
    • 2012-10-21
    相关资源
    最近更新 更多