Android TCP Server 仅在客户端关闭后显示来自 Python 客户端的消息 [英] Android TCP Server only displays messages from Python Client after Client is closed

查看:24
本文介绍了Android TCP Server 仅在客户端关闭后显示来自 Python 客户端的消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一些示例代码,它允许我从 Python 客户端向 Android 服务器 (TCP) 发送消息.但该消息仅在客户端关闭后才会显示在 Android 模拟器上.

I am using some sample code, that allows me to send a message from a Python client to an Android server (TCP). But the message only gets displayed on the Android Emulator after the client is closed.

我可能缺少对 tcp 套接字背后的一些基本了解(第一次使用和实现).

I am perhaps missing some basic understanding behind tcp sockets (first time use and implementation).

我的主要目的是让 Android 应用程序中的按钮在被点击时向单独 Linux 系统上的 Python 客户端发送不同的消息,Python 客户端在收到该消息后会发回确认.

My main intention is to have buttons in the Android App that send a different message to the Python client on a separate Linux system when clicked upon, and the Python client, after getting that message, sends back an acknowledgment.

以下是我的代码

Server.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 服务器正在侦听),消息都会被打印出来.

I have the calls to SocketServerReplyThread and related commented out, because that led to an error. Commenting that out leads to receiving the message from the Python Client but it only gets displayed on the Android Emulator after the client socket is closed. I want it to be continuous so that, whenever the client sends a message (And the android server is listening) the message gets printed.

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 个巨大的字符串.

Sockets block by default. So when you call readline, it will never return null until the socket is closed. As coded, your code will wait until all the data is read from the client and the client closes the connection, then you turn it into 1 big string and return it from convertToString. You need to rearchitect so that you handle the result of each readline call and display it, not treat everything as 1 giant string.

这篇关于Android TCP Server 仅在客户端关闭后显示来自 Python 客户端的消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆