Salutations,
je tente desesperement de mettre en place un système clients/serveur non bloquant. J'ai donc développé le code suivant coté serveur:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 public boolean connect() { try { selector = Selector.open(); serverChannel.configureBlocking(false); serverChannel.register(selector, SelectionKey.OP_ACCEPT); } catch (IOException e) { return false; } thread = new Thread(){ @Override public void run(){ while(true){ try { selector.select(); for(SelectionKey myKey : selector.selectedKeys()){ if(myKey.isAcceptable()) doAcceptable(myKey, selector); if(myKey.isValid() && myKey.isReadable()) doReadable(myKey, selector); if(myKey.isValid() && myKey.isWritable()) doWritable(myKey, selector); } selector.selectedKeys().clear(); } catch (IOException e) { // TODO Auto-generated catch block // connection ended by client e.printStackTrace(); } } }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 private void doWritable(SelectionKey myKey, Selector selector) throws IOException { System.out.println("==> Writable"); SocketChannel mySocketChannel = (SocketChannel) myKey.channel(); ByteBuffer myByteBuffer = (ByteBuffer) myKey.attachment(); myByteBuffer.flip(); int len = mySocketChannel.write(myByteBuffer); System.out.println("doWritable write : "+len); if(myByteBuffer.hasRemaining()){ myByteBuffer.compact(); } else{ if(mySocketChannel.socket().isInputShutdown()){ mySocketChannel.socket().close(); myKey.cancel(); //P2PNetwork.removeServerFromNetwork(mySocketChannel.socket().getInetAddress().getHostAddress()); } else{ myByteBuffer.clear(); myKey.interestOps(SelectionKey.OP_READ); } } System.out.println("<== Writable"); }Tout ca pour dire que j'arrive bien a me connecter à mon serveur, puis effectuer un premier dialogue (vérification de la version du client): le client envoie une requete, et le serveur répond.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 private void doReadable(SelectionKey myKey, Selector selector) throws IOException { System.out.println("==> Readable"); SocketChannel mySocketChannel = (SocketChannel)myKey.channel(); ByteBuffer myBBtoReceive = (ByteBuffer)myKey.attachment(); try{ int nb = mySocketChannel.read(myBBtoReceive); if( nb == -1){ // the stream is closed myKey.cancel(); mySocketChannel.socket().getInputStream().close(); } else if (nb > 0){ String request = null; StringBuilder requestBuilder = new StringBuilder(); byte[] tab = new byte[MAX_SIZE_BUFFER]; myBBtoReceive.flip(); for (int i = 0; i < myBBtoReceive.limit(); i++) { requestBuilder.append((char)myBBtoReceive.get()); if(requestBuilder.charAt(i) == '\n'){ if(i>0 && requestBuilder.charAt(i-1)=='\r'){ request = requestBuilder.toString(); request = request.substring(0, request.length()-2); System.out.println("requete construite: "+request); break; } } } if(request != null){ System.out.println("recu par le server: "+request); // Manage the request ... protocol.manageRequest(request, mySocketChannel.socket().getInetAddress(), mySocketChannel.socket().getPort(), null); myBBtoReceive.compact(); myKey.interestOps(SelectionKey.OP_WRITE); } else System.err.println("requete rejetee: "+new String(myBBtoReceive.array())); } }catch (IOException e) { // TODO: handle exception System.out.println("client perdu"); myKey.cancel(); mySocketChannel.close(); System.out.println("<==> Readable Exception"); } System.out.println("<== Readable"); }
Par contre, plus tard, j'effectue une autre requete via le client, bien recue par le serveur qui ne répond pas...
Voici la méthode utilisée pour répondre:
Je capte vraiment pas pourquoi ca marche pour le 1er dialogue, mais plus pour la suite. Le serveur tente bien de répondre car le write (ligne en rouge) retourne bien le nombre de caractères de la chaine a renvoyer.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 static public boolean reply(String message, String address){ // TODO vérifier que ca marche, héhéhé try{ InetAddress host = InetAddress.getByName(address); message = message + "\r\n"; for (SelectionKey key : selector.selectedKeys()) { SocketChannel sc = (SocketChannel) key.channel(); // try to send message on connected socket if(sc.socket().getInetAddress().equals(host)){ //ByteBuffer bf = (ByteBuffer)key.attachment(); System.out.println(host+" est egal a "+sc.socket().getInetAddress()); int len = sc.write(ByteBuffer.wrap(message.getBytes())); key.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE); System.out.println("Caracteres envoyes: "+len+" => "+message); return true; } } } catch(IOException e){ System.out.println("Message "+message+" can't be send: "+e.getMessage()); return false; } System.out.println("Message "+message+" has not be send: "+address+" is not found in the server list"); return false; }
Y'a surement un truc que j'ai pas capté, mais quoi? ^^
Merci d'avance pour votre aide.
Partager