10 votes

Client TCP vraiment simple

Je veux que mon application entre dans l'url de mon serveur par exemple http://192.168.1.8/ et le port par exemple 1234. Lorsque mon serveur reçoit le message de demande TCP, il renvoie un fichier (le serveur est déjà implémenté).

Je pense que je n'ai pas besoin de quelque chose de compliqué comme un AsyncTask, car je ne veux pas garder la connexion. En recevant la réponse du serveur, ma connexion doit être fermée.

Toute indication pour une avancée ou un conseil est grandement appréciée.

25voto

Daniel Nugent Points 32508

Voici un simple client TCP qui utilise des Sockets que j'ai fait fonctionner en me basant sur le code de ce tutoriel (le code du tutoriel se trouve également dans ce dépôt GitHub).

Notez que ce code est conçu pour envoyer des chaînes de caractères de va-et-vient entre le client et le serveur, généralement au format JSON.

Voici le code du client TCP :

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.1.8"; //adresse IP du serveur
    public static final int SERVER_PORT = 1234;
    // message à envoyer au serveur
    private String mServerMessage;
    // envoie des notifications de messages reçus
    private OnMessageReceived mMessageListener = null;
    // tant que c'est vrai, le serveur continuera de fonctionner
    private boolean mRun = false;
    // utilisé pour envoyer des messages
    private PrintWriter mBufferOut;
    // utilisé pour lire les messages du serveur
    private BufferedReader mBufferIn;

    /**
     * Constructeur de la classe. OnMessagedReceived écoute les messages reçus du serveur
     */
    public TcpClient(OnMessageReceived listener) {
        mMessageListener = listener;
    }

    /**
     * Envoie le message saisi par le client au serveur
     *
     * @param message texte saisi par le client
     */
    public void sendMessage(final String message) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                if (mBufferOut != null) {
                    Log.d(TAG, "Envoi : " + message);
                    mBufferOut.println(message);
                    mBufferOut.flush();
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }

    /**
     * Ferme la connexion et libère les membres
     */
    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 {
            //ici, vous devez mettre l'adresse IP de votre ordinateur.
            InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

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

            //crée un socket pour établir la connexion avec le serveur
            Socket socket = new Socket(serverAddr, SERVER_PORT);

            try {

                // envoie le message au serveur
                mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

                // reçoit le message renvoyé par le serveur
                mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                //dans cette boucle, le client écoute les messages envoyés par le serveur
                while (mRun) {

                    mServerMessage = mBufferIn.readLine();

                    if (mServerMessage != null && mMessageListener != null) {
                        //appelle la méthode messageReceived de la classe MyActivity
                        mMessageListener.messageReceived(mServerMessage);
                    }

                }

                Log.d("RÉPONSE DU SERVEUR", "S: Message Reçu : '" + mServerMessage + "'");

            } catch (Exception e) {
                Log.e("TCP", "S: Erreur", e);
            } finally {
                //le socket doit être fermé. Il n'est pas possible de se reconnecter à ce socket
                //après sa fermeture, ce qui signifie qu'une nouvelle instance de socket doit être créée.
                socket.close();
            }

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

    }

    //Déclare l'interface. La méthode messageReceived(String message) devra être implémentée dans l'Activity
    //classe à l'exécution de l'AsyncTask doInBackground
    public interface OnMessageReceived {
        public void messageReceived(String message);
    }

}

Ensuite, déclarez un TcpClient en tant que variable membre dans votre Activity :

public class MainActivity extends Activity {

    TcpClient mTcpClient;

    //............

Ensuite, utilisez un AsyncTask pour vous connecter à votre serveur et recevoir les réponses sur le thread UI (Notez que les messages reçus du serveur sont traités dans la méthode onProgressUpdate() dans l'AsyncTask) :

public class ConnectTask extends AsyncTask {

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

        //on crée un objet TCPClient
        mTcpClient = new TcpClient(new TcpClient.OnMessageReceived() {
            @Override
            //ici la méthode messageReceived est implémentée
            public void messageReceived(String message) {
                //cette méthode appelle onProgressUpdate
                publishProgress(message);
            }
        });
        mTcpClient.run();

        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        //réponse reçue du serveur
        Log.d("test", "réponse " + values[0]);
        //traiter la réponse du serveur ici....

}

Pour démarrer la connexion avec votre serveur, exécutez l'AsyncTask :

new ConnectTask().execute("");

Ensuite, envoyer un message au serveur :

//envoie le message au serveur
if (mTcpClient != null) {
    mTcpClient.sendMessage("test");
}

Vous pouvez fermer la connexion au serveur à tout moment :

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

4voto

RAIMA Points 41

Merci pour le code. Dans mon cas, j'avais des problèmes pour recevoir des données, car je n'utilisais pas un protocole basé sur des lignes. J'ai écrit une implémentation alternative qui fonctionne avec ma configuration spécifique de serveur :

  1. Dans le fichier TcpClient.java, vous devez remplacer la commande "run()" par le fragment de code ci-dessous

    public void run() {

    mRun = true;
    
    try {
        InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
        Log.e("TCP Client", "C: Connecting...");
        Socket socket = new Socket(serverAddr, SERVER_PORT);
        try {
            mBufferOut = new PrintWriter(socket.getOutputStream());
            Log.e("TCP Client", "C: Sent.");
            mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            int charsRead = 0; char[] buffer = new char[1024]; //choisissez la taille de votre tampon si vous avez besoin de plus que 1024
    
            while (mRun) {
                charsRead = mBufferIn.read(buffer);
                mServerMessage = new String(buffer).substring(0, charsRead);
                if (mServerMessage != null && mMessageListener != null) {
                    mMessageListener.messageReceived(mServerMessage);}
                mServerMessage = null;
            }
            Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'"); 

//le reste du code est OK, voir l'original

  1. doInBackground dans votre MainActivity.java envoie le message reçu à onProgressUpdate, vous pouvez l'afficher dans un autre objet tel qu'un TextView

    @Override
    protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            Log.d("test", "response " + values[0]);
            response.setText(response.getText() + "/n" +values[0]);
    } 

//"response" est un objet TextView déclaré dans votre fonction

public class MainActivity extends AppCompatActivity {
TextView response; //...ainsi de suite

et la fonction

protected void onCreate(Bundle savedInstanceState) { response = (TextView) findViewById(R.id.textView); //..ainsi de suite

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X