Android 未执行 AsyncTask - 正在尝试向 TCP 服务器发送消息

Android AsyncTask not exectued - Trying to send a message to TCP Server

我目前正在尝试从我的 Android- 智能手机向 raspberry pi 发送一条消息。 我通过此处给出的示例代码实现了一个 Android-Client:

我更改了 ip 地址和端口,因此它可以与我在 pi 上的服务器 运行ning 一起使用。该服务器是用 c 语言编写的,在切换到 android 之前,我实现了一个 C 客户端,到目前为止没有任何问题。

服务器只需要接收消息,然后打印并停止,所以非常简单。

编辑 3

我创建了用于调试和分析的新输出,我现在可能知道什么不起作用了。据我所知,SendMessageTask 从未执行过。

服务器输出现在是:

Success - create socket

Success - Binding

Listening

Success - Accept

现在它停止了,“reading...”从不打印! (应该在 while 循环中发生)

在 Android 中,我收到以下必要的输出:

D/TCP Client: C: Connecting...

D/TcpOptimizer: TcpOptimizer-ON

--> 连接发生

当我按下“发送”按钮时:

D/myMessage1: button pushed

D/myMessage: testing

但是我没有收到应该记录在 SendMessageTask

中的消息

当我单击断开连接按钮时,服务器打印:

Client disconnected

现在 Android 日志:

D/RESPONSE FROM SERVER: S: Received Message: 'null'

D/sendMessageTask: try to send message

D/TcpClient: Cannot send --> mBufferOut is null

因此我的猜测是,SendMessageTask 永远不会 运行 直到它因断开连接而失败,但为什么呢?

编辑 3 - 结束

这是(已编辑的)服务器代码:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>


int main(){
    int welcomeSocket, newSocket, read_size;
    char buffer[10000];
    struct sockaddr_in serverAddr;
    struct sockaddr_storage serverStorage;
    socklen_t addr_size;

    /*---- Create the socket. The three arguments are: ----*/
    /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
    welcomeSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (welcomeSocket == -1)    {
        printf("Could not create socket\n");
    }else {
        printf("Success - create socket\n");
    }

    /*---- Configure settings of the server address struct ----*/
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(7891);
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    /* Set all bits of the padding field to 0 */
    memset(serverAddr.sin_zero, '[=11=]', sizeof serverAddr.sin_zero);

    /*---- Bind the address struct to the socket ----*/
    if(bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0){
        printf("Error - Binding\n");
    }else {
        printf("Success - Binding\n");
    }

    /*---- Listen on the socket, with 5 max connection requests queued ----*/
    if(listen(welcomeSocket,5)==0)
        printf("Listening\n");
    else
        printf("Error\n");

    /*---- Accept call creates a new socket for the incoming connection ----*/
    addr_size = sizeof serverStorage;
    newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
    if(newSocket < 0){
        printf("Error - Accept\n");
    }else {
        printf("Success - Accept\n");
    }

    while( (read_size = recv(newSocket, buffer, 10000, 0)) > 0){
        write(newSocket, buffer, strlen(buffer));
        printf("reading...");
    }

    if(read_size == 0){
        printf("Client disconnected");
        fflush(stdout);
    }
    else if(read_size == -1){
        printf("Error - recv failed");
    }
    return 0;
}

我不太确定

中的参数是否正确
welcomeSocket = socket(AF_INET, SOCK_STREAM, 0);

仍然正确吗?

Android 中的客户端代码是:

import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

public class TcpClient {

    public static final String TAG = TcpClient.class.getSimpleName();
    public static final String SERVER_IP = "192.168.4.1"; //server IP address
    public static final int SERVER_PORT = 7891;
    // message to send to the server
    private String mServerMessage;
    // sends message received notifications
    private OnMessageReceived mMessageListener = null;
    // while this is true, the server will continue running
    private boolean mRun = false;
    // used to send messages
    private PrintWriter mBufferOut;
    // used to read messages from the server
    private BufferedReader mBufferIn;

    /**
     * Constructor of the class. OnMessagedReceived listens for the messages received from server
     */
    public TcpClient(OnMessageReceived listener) {
        mMessageListener = listener;
    }

    /**
     * Sends the message entered by client to the server
     *
     * @param message text entered by client
     */
    public void sendMessage(final String message) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                if (mBufferOut != null) {
                    Log.d(TAG, "Sending: " + message);
                    mBufferOut.println(message);
                    mBufferOut.flush();
                }else{
                    Log.d(TAG, "Cannot send --> mBufferOut is null");
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }

    /**
     * Close the connection and release the members
     */
    public void stopClient() {

        mRun = false;

        if (mBufferOut != null) {
            mBufferOut.flush();
            mBufferOut.close();
        }

        mMessageListener = null;
        mBufferIn = null;
        mBufferOut = null;
        mServerMessage = null;
    }

    public void run() {

        mRun = true;

        try {
            //here you must put your computer's IP address.
            InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

            Log.d("TCP Client", "C: Connecting...");

            //create a socket to make the connection with the server
            Socket socket = new Socket(serverAddr, SERVER_PORT);

            try {

                //sends the message to the server
                mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);


                //receives the message which the server sends back
                mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));


                //in this while the client listens for the messages sent by the server
                while (mRun) {
                    /*
                    mServerMessage = mBufferIn.readLine();

                    if (mServerMessage != null && mMessageListener != null) {
                        //call the method messageReceived from MyActivity class
                        mMessageListener.messageReceived(mServerMessage);
                    }
*/
                }

                Log.d("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");

            } catch (Exception e) {
                Log.e("TCP", "S: Error", e);
            } finally {
                //the socket must be closed. It is not possible to reconnect to this socket
                // after it is closed, which means a new socket instance has to be created.
                socket.close();
            }

        } catch (Exception e) {
            Log.e("TCP", "C: Error", e);
        }

    }

    //Declare the interface. The method messageReceived(String message) will must be implemented in the Activity
    //class at on AsyncTask doInBackground
    public interface OnMessageReceived {
        public void messageReceived(String message);
    }

}

我的(编辑过的)Mainactivity 包括用于连接的 AsyncTask 是

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Button;

public class MyActivity extends AppCompatActivity {

    private TextView mTextMessage;
    private TextView myAwesomeTextView;

    private TcpClient mTcpClient;

    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    mTextMessage.setText(R.string.title_home);
                    return true;
                case R.id.navigation_dashboard:
                    mTextMessage.setText(R.string.title_dashboard);
                    return true;
                case R.id.navigation_notifications:
                    mTextMessage.setText(R.string.title_notifications);
                    return true;
            }
            return false;
        }
    };

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

        mTextMessage = (TextView) findViewById(R.id.message);
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

        myAwesomeTextView = (TextView)findViewById(R.id.editText);

        //TCP connect
        new ConnectTask().execute("");

        //Buttons
        final Button button_Send = findViewById(R.id.button_Send);
        button_Send.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                //Set text (debugging)
                myAwesomeTextView.setText("My Awesome Text");
                Log.d("myMessage1", "button pushed ");

                //sends the message to the server
               String message = "testing[=14=]";
                //String message = "testing\n\r";

                if (mTcpClient != null) {
                    new SendMessageTask().execute(message);

                    //not needed just for debugging
                    Log.d("myMessage", "testing ");
                }

            }
        });

        final Button button_Disconnect = findViewById(R.id.button_Disconnect);
        button_Disconnect.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                if (mTcpClient != null) {
                    mTcpClient.stopClient();
                }

            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mTcpClient != null) {
            // disconnect
            new DisconnectTask().execute();
        }

    }

    /**
     * Sends a message using a background task to avoid doing long/network operations on the UI thread
     */
    public class SendMessageTask extends AsyncTask<String, Void, Void> {

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

            // send the message
            mTcpClient.sendMessage(params[0]);

            Log.d("sendMessageTask", "try to send message ");


            return null;
        }

        @Override
        protected void onPostExecute(Void nothing) {
            super.onPostExecute(nothing);

            //nothing to do yet
        }
    }

    /**
     * Disconnects using a background task to avoid doing long/network operations on the UI thread
     */
    public class DisconnectTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... voids) {

            // disconnect
            mTcpClient.stopClient();
            mTcpClient = null;

            return null;
        }

        @Override
        protected void onPostExecute(Void nothing) {
            super.onPostExecute(nothing);

            //nothing to do yet
        }
    }

    public class ConnectTask extends AsyncTask<String, String, TcpClient> {

        @Override
        protected TcpClient doInBackground(String... message) {

            //we create a TCPClient object and
            mTcpClient = new TcpClient(new TcpClient.OnMessageReceived() {
                @Override
                //here the messageReceived method is implemented
                public void messageReceived(String message) {
                    //this method calls the onProgressUpdate
                    publishProgress(message);
                }
            });
            mTcpClient.run();

            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);

            Log.d("test", "response " + values[0]);
            //process server response here....
        }
    }
}

编辑#2(失败行为仍然存在)

我设法让它工作了。

我改线了

new SendMessageTask().execute(message);

new SendMessageTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, message);

这使发送工作正常。

我也将服务器代码更改为:

#define MAX 2048
#define PORT 7891
#define SA struct sockaddr

// Function designed for chat between client and server.
void communicate(int sockfd)
{
    char buff[MAX];
    int n;
    // infinite loop for chat
    for (;;) {
        bzero(buff, MAX);

        // read the message from client and copy it in buffer
        read(sockfd, buff, sizeof(buff));
        // print buffer which contains the client contents
        printf("From client: %s\t To client : ", buff);
        bzero(buff, MAX);
        n = 0;
        // copy server message in the buffer
        while ((buff[n++] = getchar()) != '\n');

        // and send that buffer to client
        write(sockfd, buff, sizeof(buff));

        // if msg contains "Exit" then server exit and chat ended.
        if (strncmp("exit", buff, 4) == 0) {
            printf("Server Exit...\n");
            break;
        }

    }
}

// Driver function
int main()
{
    int sockfd, connfd, len;
    struct sockaddr_in servaddr, cli;

    // socket create and verification
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("socket creation failed...\n");
        exit(0);
    }
    else
        printf("Socket successfully created..\n");
    bzero(&servaddr, sizeof(servaddr));

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT);

    // Binding newly created socket to given IP and verification
    if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
        printf("socket bind failed...\n");
        exit(0);
    }
    else
        printf("Socket successfully binded..\n");

    // Now server is ready to listen and verification
    if ((listen(sockfd, 5)) != 0) {
        printf("Listen failed..\n");
        exit(0);
    }
    else
        printf("Server listening...\n");
    len = sizeof(cli);

    // Accept the data packet from client and verification
    connfd = accept(sockfd, (SA*)&cli, &len);
    if (connfd < 0) {
        printf("server acccept failed...\n");
        exit(0);
    }
    else
        printf("server acccept the client..\n");

    // Function for chatting between client and server
    communicate(connfd);

    // After chatting close the socket
    if(close(sockfd) < 0){
        printf("Error - closing socket...\n");
    }
    else{
        printf("Socket successfully closed..\n");
    }
}