2015-11-06 185 views
0

我知道這個問題已經被問過,我嘗試了不同的解決方案,但我被困在執行部分.. :(服務器發送消息到所有連接的客戶端

目前多個客戶端可以連接到服務器,我使用了javadocs的多線程KnockKnock服務器/客戶端示例,並稍微編輯它,以便您可以將消息發送到服務器,並將其回顯給您,但我希望能夠使它如果客戶端1發送消息,則服務器會將它們廣播回所有連接到服務器的客戶端。

我試過環顧四周,看到與我現在在同一位置的人,並且他們被告知做一個列表以跟蹤所有連接,然後遍歷列表併發送消息,但我真的不知道在哪個類中放置它或如何處理它。

如果有人能告訴我或者只是給我暗示的地方,我應該開始,這將不勝感激,因爲我真的只是停留在那一刻:(

這裏我也正是我在至今:

服務器:

import java.io.IOException; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.ArrayList; 
import java.util.List; 

public class Server { 



    public static void main(String[] args) throws IOException { 



     boolean listening = true; 

     try (ServerSocket serverSocket = new ServerSocket(4444)) { 

      while (listening) { 
       ServerThread thread = new ServerThread(serverSocket.accept()); 
       thread.start(); 
      } 
     } catch (IOException e) { 
      System.err.println("Could not listen on port "); 
      System.exit(-1); 
     } 
    } 



} 

ServerThread

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.Socket; 
import java.util.ArrayList; 
import java.util.List; 


public class ServerThread extends Thread{ 



    private Socket socket = null; 



    public ServerThread(Socket socket) { 
     super("MultiServerThread"); 
     this.socket = socket; 

    } 

    public void run() { 

     try (
       PrintWriter out = new PrintWriter(socket.getOutputStream(), true); 
       BufferedReader in = new BufferedReader(
         new InputStreamReader(
           socket.getInputStream())); 
     ) { 

      while (true) { 


       String input = in.readLine(); 
       System.out.println(input); 
       out.println("ecco " + input); 



       if (input.equals("Bye")) 
        break; 
      } 
      socket.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 


} 

客戶端(未確定是否有必要,但這裏是它反正)

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.Socket; 
import java.net.UnknownHostException; 


public class Client { 

    public static void main(String[] args) throws IOException { 


     try (
       Socket kkSocket = new Socket("172.30.242.51", 4444); 
       PrintWriter out = new PrintWriter(kkSocket.getOutputStream(), true); 
       BufferedReader in = new BufferedReader(
         new InputStreamReader(kkSocket.getInputStream())); 
     ) { 
      BufferedReader stdIn = 
        new BufferedReader(new InputStreamReader(System.in)); 

      while (true) { 

       if(in != null) { 

        String input = stdIn.readLine(); 
        out.println("Client: " + input); 
        System.out.println(in.readLine()); 
        out.flush(); 

       } 

      } 
     } catch (UnknownHostException e) { 
      System.err.println("Don't know about host "); 
      System.exit(1); 
     } catch (IOException e) { 
      System.err.println("Couldn't get I/O for the connection to "); 
      System.exit(1); 
     } 
    } 
} 

週末愉快=)

回答

0

操作「寫」在你的榜樣封鎖。因此,通過所有連接迭代可能會導致延遲並阻止您的推送線程。如果你不想有內存泄漏,也總是爲套接字設置SO_TIMEOUT。

我建議使用netty server

它有將數據推送到所有連接的客戶非常好的功能 - 尋找ChannelGroup

0

你爲什麼不使用NIO來解決這個問題?

一個簡單的例子:

public class EchoServer { 

    public static void main(String[] args) throws Exception { 
    //Create TCP server channel 
    ServerSocketChannel serv = ServerSocketChannel.open(); 
    ServerSocket sock = serv.socket(); 

    //Create a socket on your IP and port (i.e: localhost:12345) 
    SocketAddress addr = new InetSocketAddress(12345); 

    //Bind server socket and socket address 
    sock.bind(addr); 

    //Configure socket so all its methods won't be blocking 
    serv.configureBlocking(false); 

    //Create a selector to attend all the incoming requests 
    Selector selector = Selector.open(); 

    //Register into the selector the accept request type 
    serv.register(selector,SelectionKey.OP_ACCEPT); 

    //Create a common buffer 
    ByteBuffer commonBuffer = ByteBuffer.allocate(10000); 
    commonBuffer.clear(); 

    Iterator<SelectionKey> it = null; 
    ByteBuffer channelBuffer = null; 
    for (;;){ //Infinite loop 

     System.out.println("Waiting for events......"); 
     selector.select(); // This call do is blocking 

     System.out.println("New event received"); 

     it = selector.selectedKeys().iterator(); 

     while(it.hasNext()) { 
      SelectionKey key = (SelectionKey) it.next(); 
      System.out.println(String.format("Processing %s", key)); 
      it.remove(); // Remove it to avoid duplications 

      try{ 
       if (key.isAcceptable()) { 
        System.out.println("Received new connection request"); 
        processConnectionRequest(serv, selector); 
       }else if (key.isReadable()) { 
        System.out.println("Received new reading request"); 
        processReadingRequest(selector, commonBuffer, key); 
       }else if (key.isWritable()) { 
        System.out.println("Received new writing request"); 
        processWritingRequest(key); 
       } 
      }catch(Exception e){ 
       key.cancel(); 
       try { 
        key.channel().close(); 
       } catch (Exception ce) {} 
      }//end catch 
     }//end while 
    }//end for 
    }//end main 

    private static void processWritingRequest(SelectionKey key) throws IOException { 
    SocketChannel cli = (SocketChannel) key.channel(); 
    ByteBuffer buf = (ByteBuffer) key.attachment(); 

    System.out.println(String.format("Wrinting into the channel %s", cli)); 
    buf.flip();//prepare the buffer 
    buf.rewind(); 
    cli.write(buf); 

    if (buf.hasRemaining()) { 
     //If there is more content remaining, compact the buffer  
     buf.compact(); 
    } else { 
     buf.clear(); 
     key.interestOps(SelectionKey.OP_READ); 
    } 
    } 

    private static void processReadingRequest(Selector selector, ByteBuffer commonBuffer, SelectionKey key) 
     throws IOException { 
    SocketChannel cli = (SocketChannel) key.channel(); 


    if (cli.read(commonBuffer) == -1) { 
     System.out.println(String.format("Closing channel %s", cli)); 
     cli.close(); // internally calls key.cancel() 
    } 
    else {//Send the data to all the channels 

     commonBuffer.flip();//prepare the buffer 
     Iterator<SelectionKey> it2 = selector.keys().iterator(); 
     System.out.println("Writing data to all the channels"); 
     SelectionKey keys = null; 
     while(it2.hasNext()) { 
      keys = it2.next(); 
      System.out.println(String.format("Writing in %s", keys)); 

      ByteBuffer buf = (ByteBuffer) keys.attachment(); 

      if(buf!=null) 
      { 
      buf.put(commonBuffer); 
      keys.interestOps(SelectionKey.OP_WRITE|SelectionKey.OP_READ); 

      commonBuffer.rewind(); 
      } 

     } 
     commonBuffer.clear(); 

    } 
    } 

    private static void processConnectionRequest(ServerSocketChannel serv, Selector selector) 
     throws IOException, ClosedChannelException { 
    ByteBuffer channelBuffer; 
    SocketChannel cli = serv.accept(); 
    cli.configureBlocking(false); 
    channelBuffer = ByteBuffer.allocate(10000); 
    System.out.println(String.format("Registering new reading channel: %s", cli)); 
    cli.register(selector, SelectionKey.OP_READ, channelBuffer); 
    } 
} 
+0

很抱歉,但這個看起來很混亂,我:( –

相關問題