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

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

问题描述

我使用的一些示例code,可以让我从一个Python客户端发送消息到Android服务器(TCP)。但消息只获取客户机关闭后的And​​r​​oid模拟器显示。

我也许缺少TCP套接字(第一次使用与实施)背后的一些基本的了解。

我的主要目的是在Android应用程序,当在点击发送不同的消息给Python客户端独立的Linux系统上的按钮,和Python客户端,获得该消息后,发回确认。

以下是我的code

Server.java

 包test.server2;进口java.io.BufferedReader中;
进口java.io.IOException异常;
进口的java.io.InputStream;
进口java.io.InputStreamReader中;
进口java.io.OutputStream中;
进口java.io.PrintStream中;
进口java.net.InetAddress中;
进口java.net.NetworkInterface;
进口java.net.ServerSocket的;
进口的java.net.Socket;
进口java.net.SocketException异常;
进口的java.util.Enumeration;公共类服务器{
    MainActivity活动;
    ServerSocket的ServerSocket的;
    字符串消息=;
    静态最终诠释socketServerPORT = 8080;    公共服务器(MainActivity活动){
        this.activity =活动;
        螺纹socketServerThread =新主题(新SocketServerThread());
        socketServerThread.start();
    }    公众诠释的getPort(){
        返回socketServerPORT;
    }    公共无效的onDestroy(){
        如果(ServerSocket的!= NULL){
            尝试{
                serverSocket.close();
            }赶上(IOException异常五){
                // TODO自动生成catch块
                e.printStackTrace();
            }
        }
    }    私有类SocketServerThread继承Thread {        诠释计数= 0;        @覆盖
        公共无效的run(){
            尝试{
                //使用指定的端口建立的ServerSocket
                ServerSocket的=新的ServerSocket(socketServerPORT);                而(真){
                    //阻止呼叫,直到建立连接,并退回
                    // Socket对象
                    Socket套接字的ServerSocket.accept =();
                    算上++;
                    InputStream的消息2 = socket.getInputStream();
                    最后弦乐的messageReceived = convertToString(消息2);                    activity.runOnUiThread(新的Runnable(){
                        @覆盖
                        公共无效的run(){
                            activity.msg.setText(的messageReceived);
                        }
                    });
                    // SocketServerReplyThread socketServerReplyThread =
                      //新SocketServerReplyThread(插座,计数);
                    //socketServerReplyThread.run();                }
            }赶上(IOException异常五){
                // TODO自动生成catch块
                e.printStackTrace();
                消息+ =不对!+ e.toString()+\\ n;
            }
            activity.runOnUiThread(新的Runnable(){                @覆盖
                公共无效的run(){
                    activity.msg.setText(消息);
                }
            });
        }
    }    私有类SocketServerReplyThread继承Thread {        私人插座hostThreadSocket;
        INT CNT;        SocketServerReplyThread(Socket套接字,诠释三){
            hostThreadSocket =插座;
            CNT = C;
        }        @覆盖
        公共无效的run(){
            的OutputStream的OutputStream;
            字符串msgReply =你好,从服务器,你是#+ CNT;            尝试{
                的OutputStream = hostThreadSocket.getOutputStream();
                为PrintStream PrintStream的=新的PrintStream(OutputStream中);
                printStream.print(msgReply);
                printStream.close();                消息+ =重播:+ msgReply +\\ n;                activity.runOnUiThread(新的Runnable(){                    @覆盖
                    公共无效的run(){
                        activity.msg.setText(消息);
                    }
                });
            }赶上(IOException异常五){
                // TODO自动生成catch块
                e.printStackTrace();
                消息+ =不对!+ e.toString()+\\ n;
            }            activity.runOnUiThread(新的Runnable(){                @覆盖
                公共无效的run(){
                    activity.msg.setText(消息);
                }
            });
        }    }    私人字符串convertToString(InputStream的消息){
        读者的BufferedReader =新的BufferedReader(新的InputStreamReader(消息));
        StringBuilder的StringBuilder的=新的StringBuilder();        串线= NULL;
        尝试{
            而((行= reader.readLine())!= NULL){
                //stringbuilder.append(line).append('\
');
                stringbuilder.append(线);
            }
        }赶上(IOException异常五){
            e.printStackTrace();
        } {最后
            尝试{
                message.close();
                //reader.close();
            }赶上(IOException异常五){
                e.printStackTrace();
            }
        }
        返回stringbuilder.toString();
    }    公共字符串getIpAddress(){
        串的ip =;
        尝试{
            枚举<&NetworkInterface的GT; enumNetworkInterfaces =的NetworkInterface
                    .getNetworkInterfaces();
            而(enumNetworkInterfaces.hasMoreElements()){
                的NetworkInterface的NetworkInterface = enumNetworkInterfaces
                        .nextElement();
                枚举<&的InetAddress GT; enumInetAddress =的NetworkInterface
                        .getInetAddresses();
                而(enumInetAddress.hasMoreElements()){
                    InetAddress类InetAddress类= enumInetAddress
                            .nextElement();                    如果(inetAddress.isSiteLocalAddress()){
                        IP + =服务器在运行
                                + inetAddress.getHostAddress();
                    }
                }
            }        }赶上(SocketException E){
            // TODO自动生成catch块
            e.printStackTrace();
            IP + =不对!+ e.toString()+\\ n;
        }
        返回的IP;
    }
}

我要SocketServerReplyThread及相关注释掉的调用,因为这导致了一个错误。谈到了这一点导致接收从Python客户端的消息,但客户端的socket被关闭后,只拿到Android模拟器显示。我想,这样,每当客户端发送消息(以及Android服务器侦听)获取打印的消息时,它是连续的。

MainActivity.java

 包test2.server;进口android.os.Bundle;
进口android.support.design.widget.FloatingActionButton;
进口android.support.design.widget.Snackbar;
进口android.support.v7.app.AppCompatActivity;
进口android.support.v7.widget.Toolbar;
进口android.view.View;
进口android.view.Menu;
进口android.view.MenuItem;
进口android.widget.TextView;公共类MainActivity扩展AppCompatActivity {
    Server服务器;
    TextView的infoip,味精;    @覆盖
    保护无效的onCreate(捆绑savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);
        工具条工具栏=(栏)findViewById(R.id.toolbar);
        setSupportActionBar(工具栏);        FloatingActionButton FAB =(FloatingActionButton)findViewById(R.id.fab);
        fab.setOnClickListener(新View.OnClickListener(){
            @覆盖
            公共无效的onClick(查看视图){
                Snackbar.make(看来,用自己的行动替换,Snackbar.LENGTH_LONG)
                        .setAction(动作,NULL).show();
            }
        });        infoip =(的TextView)findViewById(R.id.infoip);
        味精=(的TextView)findViewById(R.id.msg);
        服务器=新服务器(本);
        infoip.setText(server.getIpAddress()+:+ server.getPort());    }
    @覆盖
    保护无效的onDestroy(){
        super.onDestroy();
        server.onDestroy();
    }
}

Python客户端

 #!的/ usr / bin中/蟒蛇进口插座
进口时间
S = socket.socket(socket.AF_INET,socket.SOCK_STREAM)主机=127.0.0.1
端口= 4534
s.connect((主机,端口))
s.send(谢谢你的连接+\\ n)
time.sleep(10)#added检查关闭与否之前,如果它被显示
S.CLOSE()


解决方案

在默认情况下套接字块。所以,当你调用readline的,它永远不会直到关闭套接字返回null。作为codeD,你code将等到所有的数据从客户端读取和客户端关闭连接,然后你把它变成1大串并convertToString返回。您需要重新构建,让你处理每个readline的调用的结果并显示它,不要把一切都为1巨大的字符串。

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.

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

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.

Following is my code

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;
    }
}

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 client

#!/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()

解决方案

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天全站免登陆