当前位置: 首页 > 面试题库 >

关闭客户端后,Android TCP Server仅显示来自Python客户端的消息

洪英豪
2023-03-14
问题内容

我正在使用一些示例代码,该代码使我可以将消息从Python客户端发送到Android服务器(TCP)。但是,仅在关闭客户端后,该消息才会显示在Android仿真器上。

我可能缺少tcp套接字(首​​次使用和实现)背后的一些基本知识。

我的主要目的是使Android
App中的按钮可以在单击时将不同的消息发送到单独的Linux系统上的Python客户端,并且Python客户端在收到该消息后会发送回确认。

以下是我的代码

服务器.java

package test.server2;



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

public class Server {
    MainActivity activity;
    ServerSocket serverSocket;
    String message = "";
    static final int socketServerPORT = 8080;

    public Server(MainActivity activity) {
        this.activity = activity;
        Thread socketServerThread = new Thread(new SocketServerThread());
        socketServerThread.start();
    }

    public int getPort() {
        return socketServerPORT;
    }

    public void onDestroy() {
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private class SocketServerThread extends Thread {

        int count = 0;

        @Override
        public void run() {
            try {
                // create ServerSocket using specified port
                serverSocket = new ServerSocket(socketServerPORT);

                while (true) {
                    // block the call until connection is created and return
                    // Socket object
                    Socket socket = serverSocket.accept();
                    count++;


                    InputStream message2 = socket.getInputStream();
                    final String messageReceived = convertToString(message2);

                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            activity.msg.setText(messageReceived);
                        }
                    });


                    //SocketServerReplyThread socketServerReplyThread =
                      //      new SocketServerReplyThread(socket, count);
                    //socketServerReplyThread.run();

                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                message += "Something wrong! " + e.toString() + "\n";
            }
            activity.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    activity.msg.setText(message);
                }
            });
        }
    }

    private class SocketServerReplyThread extends Thread {

        private Socket hostThreadSocket;
        int cnt;

        SocketServerReplyThread(Socket socket, int c) {
            hostThreadSocket = socket;
            cnt = c;
        }

        @Override
        public void run() {
            OutputStream outputStream;
            String msgReply = "Hello from Server, you are #" + cnt;

            try {
                outputStream = hostThreadSocket.getOutputStream();
                PrintStream printStream = new PrintStream(outputStream);
                printStream.print(msgReply);
                printStream.close();

                message += "replayed: " + msgReply + "\n";

                activity.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        activity.msg.setText(message);
                    }
                });


            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                message += "Something wrong! " + e.toString() + "\n";
            }

            activity.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    activity.msg.setText(message);
                }
            });
        }

    }

    private String convertToString(InputStream message) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(message));
        StringBuilder stringbuilder = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                //stringbuilder.append(line).append('\n');
                stringbuilder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                message.close();
                //reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return stringbuilder.toString();
    }

    public String getIpAddress() {
        String ip = "";
        try {
            Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
                    .getNetworkInterfaces();
            while (enumNetworkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = enumNetworkInterfaces
                        .nextElement();
                Enumeration<InetAddress> enumInetAddress = networkInterface
                        .getInetAddresses();
                while (enumInetAddress.hasMoreElements()) {
                    InetAddress inetAddress = enumInetAddress
                            .nextElement();

                    if (inetAddress.isSiteLocalAddress()) {
                        ip += "Server running at : "
                                + inetAddress.getHostAddress();
                    }
                }
            }

        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            ip += "Something Wrong! " + e.toString() + "\n";
        }
        return ip;
    }
}

我已将对SocketServerReplyThread的调用及相关内容注释掉了,因为这导致了错误。注释掉该内容会导致从Python客户端接收消息,但是只有在关闭客户端套接字后,它才会显示在Android仿真器上。我希望它是连续的,以便每当客户端发送一条消息(并且android服务器正在侦听)时,该消息就会被打印出来。

MainActivity.java

package test2.server;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    Server server;
    TextView infoip, msg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();


            }
        });

        infoip = (TextView) findViewById(R.id.infoip);
        msg = (TextView) findViewById(R.id.msg);
        server = new Server(this);
        infoip.setText(server.getIpAddress() + ":" + server.getPort());

    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        server.onDestroy();


    }
}

Python客户端

#!/usr/bin/python

import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = "127.0.0.1" 
port = 4534
s.connect((host, port))


s.send("Thank you for connecting" + '\n')
time.sleep(10) #added to check if it gets displayed before closing or not
s.close()

问题答案:

默认情况下,套接字阻止。因此,当您调用readline时,在关闭套接字之前,它将永远不会返回null。按照编码,您的代码将等待,直到从客户端读取了所有数据并且客户端关闭了连接,然后将其变成1个大字符串并从convertToString返回。您需要重新配置,以便处理每个readline调用的结果并显示它,而不是将所有内容都视为1个巨型字符串。



 类似资料:
  • Python 客户端 前面应用案例,都是直接通过 HTTP API 来跟 hyperledger 进行交互,操作比较麻烦。 还可以直接通过 hyperledger-py 客户端来进行更方便的操作。 安装 $ pip install hyperledger --upgrade 或直接源码安装 $ git clone https://github.com/yeasy/hyperledger-py.g

  • socket.io 0.9 node.js 0.10.15 速递3.3.4 即:调用 --服务器端 --客户端

  • 问题内容: 如何关闭客户端的套接字连接? 我在用: socket.io 0.9 node.js 0.10.15 express3.3.4 即:呼叫 -服务器端 - 客户端 如果加载测试页,则需要来自服务器的一些值(getInitData)。 在第一页上,我获取一次数据,在重新加载或第二遍上,我获取两次数据,依此类推。 重新加载页面以及离开页面后,服务器端的连接将自动关闭。 但是在客户端,连接仍然打

  • 我刚刚开始使用hazelcast[3.3.1]。根据hazelcast应用程序和客户端教程,我创建了一个hazelcast应用程序实例和一个客户端(使用eclipse IDE)。 从客户端,我能够将对象添加到地图并成功获取它们。但是,我在实例的控制台上看到以下警告,它们似乎警告客户端断开连接。这是每个客户端get/put的正常行为吗? 在退出客户端程序之前,是否有适当的方法断开客户端与实例的连接?

  • 我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我最初的想法如下: 我在服务器上制作了一个中央服务器插座,所有应用程序都可以连接到该插座。此ServerSocket跟踪已连接的套接字(客户端),并将新连接的客户端的IP和端口提供给所有其他客户端。每个客户端都会创建一个新的ServerSocket,所有客户端都可以连接到它。 换句话说:每个客户端都有一个Se

  • 下面是AWS Ec2中Mongo的副本设置,io1(10000 iops)和r4。8XL码 1个主节点、1个辅助节点、1个仲裁节点 我们有2种类型的应用程序写入/读取Mongo,几乎数据接近2亿 现在,我们从Mongo获得readtimeout/sockettimeour,而application1在Mongo上几乎没有写操作,而application2在Mongo上执行大量写操作 Applica