2011-03-28 65 views
0

我改編此代碼How to send and receive serialized object in socket channel我的實時模擬發送對象,但我一個接一個地運行到異常是因爲此代碼阻止自然界如何將此代碼轉換到非阻塞與javanio使用javanio從阻塞轉移到非阻塞I/O

/* 
    * Writer 
    */ 
    import java.io.IOException; 
    import java.io.ObjectOutputStream; 
    import java.net.InetSocketAddress; 
    import java.nio.channels.ServerSocketChannel; 
    import java.nio.channels.SocketChannel; 

    public class CleanSender implements Runnable { 

     private SimManager SM; 
     private BallState ballState = new BallState(10, 5); 
     private ServerSocketChannel ssChannel; 

     private Thread tRunSer = new Thread(this, "ServerSelectThread"); 

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

     CleanSender server = new CleanSender(); 
     server.startServer(); 

    } 

    private void startServer() throws IOException { 
     ssChannel = ServerSocketChannel.open(); 
     ssChannel.configureBlocking(true); 
     int port = 2345; 
     ssChannel.socket().bind(new InetSocketAddress(port)); 
     // SM = new SimManager(this, BS); 
     // SM.start(); // GameEngine thread starting here 
     tRunSer.start(); 
    } 

    public void run() { 
     try { 
      SocketChannel sChannel = ssChannel.accept(); 

      while (true) { 

       ObjectOutputStream oos = new ObjectOutputStream(sChannel 
         .socket().getOutputStream()); 
       oos.writeObject(ballState); 
       System.out.println("Sending String is: '" + ballState.X + "'" + ballState.Y); 
       oos.close(); 
       System.out.println("Sender Start"); 
       System.out.println("Connection ended"); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

客戶:其不斷將尋找答覆從服務器

import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.net.InetSocketAddress; 
import java.nio.channels.SocketChannel; 

public class CleanReceiver implements Runnable { 

    private SocketChannel sChannel; 
    private Thread receiverThread = new Thread(this, "receiverThread"); 


    private synchronized void startServer() throws IOException { 
     sChannel = SocketChannel.open(); 
     sChannel.configureBlocking(true); 
     if (sChannel.connect(new InetSocketAddress("localhost", 2345))) { 
      receiverThread.start(); 
     } 
    } 
public void run() { 

    while (true) { 
     try { 
      ObjectInputStream ois = new ObjectInputStream(sChannel.socket() 
        .getInputStream()); 

      BallState s = (BallState) ois.readObject(); 
      System.out.println("String is: '" + s.X + "'" + s.Y); 
      ois.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 

     System.out.println("End Receiver"); 
    } 
} 


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

      CleanReceiver rc=new CleanReceiver(); 
      rc.startServer(); 

      System.out.println("End Receiver"); 
     } 
} 

將在這個場景中設計工作時,服務器必須保持連接客戶端同時向已連接的客戶端發送模擬狀態?,我在找專家一瞥。

感謝,

jibbylala

回答

0

你的代碼有兩個主要問題:

  • 處理每一個對象,導致關閉相關的後您關閉流套接字,因此它們不再有效,不能用於處理以下對象。在接收端,根本不需要close(),在發送端使用flush()而不是close()來確保緩衝區被刷新。

  • 實施阻塞IO時,您(通常)需要在服務器上爲每個客戶端啓動一個新線程。它將允許您同時與多個客戶端通信。在這種情況下請注意線程同步問題!

如果有每個客戶端一個線程是不適合你接受,你可以在一個非阻塞的方式實現服務器,但是,正如已經由彼得Lawrey表示,這是比較複雜的,所以我建議你得到它首先阻止IO。

1

如果您正在使用的ObjectInputStream或ObjectOutputStream的,我建議你堅持使用阻塞IO。對這些庫使用非阻塞IO是沒有真正好處的10倍。

您是否考慮過使用ServerSocketSocket代替NIO。這將是更容易使用,什麼對象流是記事的原始設計爲使用,

+0

我認爲我遇到的問題是因爲阻止自然或? – 2011-03-28 14:02:56