2 votes

Problème avec une tâche réseau bloquante

Je suis novice en Java, alors pardonnez les erreurs obscènes que je pourrais commettre :)

Je développe un programme en Java qui doit, entre autres, gérer les clients qui se connectent à un serveur. Le serveur a 3 threads en cours d'exécution, et je les ai créés de la manière suivante :

DaemonForUI du;
DaemonForPort da;
DaemonForCheck dc;

da = new DaemonForPort(3);
dc = new DaemonForCheck(5);
du = new DaemonForUI(7);

Thread t_port = new Thread(da);
Thread t_check = new Thread(dc);
Thread t_ui = new Thread(du);

t_port.setName("v1.9--PORTd");
t_check.setName("v1.9-CHECKd");
t_ui.setName("v1.9----UId");

t_port.start();
t_check.start();
t_ui.start();

Chaque thread gère un aspect différent du programme complet. Le thread t_ui est chargé d'accepter les connexions entrantes asynchrones des clients, de traiter les données envoyées et de renvoyer d'autres données au client. Lorsque je supprime toutes les commandes du morceau de code précédent qui ont trait au thread t_ui, tout fonctionne correctement, ce qui, dans mon cas, signifie que les autres threads affichent leurs messages de débogage.

Si je règle le thread t_ui pour qu'il s'exécute aussi, tout le programme se bloque à l'acceptation du thread t_ui.

Après avoir lu des manuels en ligne, j'ai vu que les connexions acceptées devaient être non bloquantes, et j'ai donc utilisé quelque chose comme ça :

public ServerSocketChannel ssc = null;

ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(port));
ssc.configureBlocking(false);

SocketChannel sc = ssc.accept();

if (sc == null) {
    ;
}
else {
    System.out.println("The server and client are connected!");
    System.out.println("Incoming connection from: " + sc.socket().getRemoteSocketAddress());
    in = new DataInputStream(new BufferedInputStream(sc.socket().getInputStream()));
    out = new DataOutputStream(new BufferedOutputStream(sc.socket().getOutputStream()));
    //other magic things take place after that point...

Le fil de discussion pour t_ui est créé comme suit :

class DaemonForUI implements Runnable{
    private int cnt;
    private int rr;
    public ListenerForUI serverListener;

    public DaemonForUI(int rr){
        cnt = 0;
        this.rr = rr;
        serverListener = new ListenerForUI();
    }

    public static String getCurrentTime() {
        final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss";
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
        return (sdf.format(cal.getTime()));
    }

    public void run() {
        while(true) {
            System.out.println(Thread.currentThread().getName() + "\t (" + cnt + ")\t (every " + rr + " sec) @ " + getCurrentTime());
            try{
                Thread.sleep(rr * 1000);
                cnt++;
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

Manifestement, je fais quelque chose de mal lors de la création du socket ou lors de l'utilisation du thread. Savez-vous ce qui cause le problème ?

Toute aide serait grandement appréciée.

1voto

EJP Points 113412

N'utilisez pas d'E/S non bloquantes tant que vous n'êtes pas sûr d'en avoir besoin. Démarrez simplement un nouveau thread pour chaque socket accepté, ainsi que pour les threads qui l'acceptent.

0voto

Sotiris Points 86

Problème résolu :) J'ai pris connaissance de vos suggestions et j'ai regardé le code de plus près. C'était une erreur de conception car j'avais une fonction qui créait une boucle while(true) dans le constructeur de DaemonForUI (et plus précisément dans ListenerForUI()). Cela obligeait tout le programme à passer par l'instruction while, ce qui bloquait toutes les autres actions.

Une erreur stupide, je dois l'admettre... :(

Merci à tous ceux qui ont répondu à ma question.

Je vais étudier l'idée mentionnée de créer un nouveau fil de discussion pour chaque connexion entrante. La tâche à accomplir pour chaque connexion entrante n'étant pas très lourde, j'ai pensé qu'un seul thread pourrait faire l'affaire.

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