上善若水
          In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
          posts - 146,comments - 147,trackbacks - 0
          在看Jetty源碼中的EndPointTest類,對(duì)EndPoint的測(cè)試,我的思路是:
          1. 建立一個(gè)連接(創(chuàng)建ServerSocket實(shí)例,一般還會(huì)給定一個(gè)端口,其實(shí)可以bind(null)以讓操作系統(tǒng)分配一個(gè)可用端口),新啟動(dòng)一個(gè)線程,在新線程中監(jiān)聽(tīng)給定端口(調(diào)用accept方法)。
          2. 發(fā)送客戶端請(qǐng)求(創(chuàng)建一個(gè)Socket實(shí)例,并向該Socket寫入請(qǐng)求數(shù)據(jù))。
          3. 在接收端讀取數(shù)據(jù),驗(yàn)證寫入的請(qǐng)求和接收到的數(shù)據(jù)相同。

          在以上流程實(shí)現(xiàn)中,accept方法返回的接收端Socket需要傳給主線程,同時(shí)要保證使用該Socket是在accept方法返回之后,以我習(xí)慣,我會(huì)使用一個(gè)Lock或CountDownLatch:
          private static class SocketHolder {
              Socket socket;
          }

          @Test
          public void levinOldWayTest() throws Exception {
              final ServerSocket server = new ServerSocket(10240);
              
              final CountDownLatch latch = new CountDownLatch(1);
              final SocketHolder socketHolder = new SocketHolder();
              new Thread() {
                  public void run() {
                      try {
                          socketHolder.socket = server.accept();
                          latch.countDown();
                      } catch(Exception ex) {
                          ex.printStackTrace();
                      }
                  }
              }.start();
              
              Socket socket = new Socket(server.getInetAddress(), server.getLocalPort());
              socket.getOutputStream().write("My Test String".getBytes());
              
              latch.await(5, TimeUnit.SECONDS);
              byte[] receives = new byte[4096];
              int length = socketHolder.socket.getInputStream().read(receives);
              
              assertEquals("My Test String", new String(receives, 0, length));
              
              socket.close();
              socketHolder.socket.close();
              server.close();
          }

          不知道有多少人也像我一樣把這段代碼寫成這樣?這里有兩個(gè)問(wèn)題:
          1. ServerSocket的監(jiān)聽(tīng)的端口不一定是可用的,類似測(cè)試代碼我之前沒(méi)有寫過(guò),我估計(jì)自己正真在寫的時(shí)候應(yīng)該會(huì)想到讓操作系統(tǒng)動(dòng)態(tài)分配。
          2. 為了在兩個(gè)線程中傳遞數(shù)據(jù),這里首先創(chuàng)建了一個(gè)SocketHolder類,然后使用CountDownLatch,寫起來(lái)好麻煩。為了簡(jiǎn)化這段代碼,可以使用Exchanger,即當(dāng)一個(gè)生產(chǎn)者線程準(zhǔn)備好數(shù)據(jù)后可以通過(guò)Exchanger將數(shù)據(jù)傳遞給消費(fèi)者,而消費(fèi)者在生產(chǎn)者傳遞過(guò)來(lái)數(shù)據(jù)后就可以消費(fèi)了,這里的數(shù)據(jù)就是Socket。

          改進(jìn)后的代碼如下:
          @Test
          public void levinImprovedWayTest() throws Exception {
              final ServerSocket server = new ServerSocket();
              server.bind(null);
              
              final Exchanger<Socket> exchanger = new Exchanger<Socket>();
              new Thread() {
                  public void run() {
                      try {
                          exchanger.exchange(server.accept());
                      } catch(Exception ex) {
                          ex.printStackTrace();
                      }
                  }
              }.start();
              
              Socket socket = new Socket(server.getInetAddress(), server.getLocalPort());
              socket.getOutputStream().write("My Test String".getBytes());
              
              Socket receiverSocket = exchanger.exchange(null, 5, TimeUnit.SECONDS);
              byte[] receives = new byte[4096];
              int length = receiverSocket.getInputStream().read(receives);
              
              assertEquals("My Test String", new String(receives, 0, length));
              
              socket.close();
              receiverSocket.close();
              server.close();
          }
          posted on 2014-03-23 13:40 DLevin 閱讀(1487) 評(píng)論(0)  編輯  收藏 所屬分類: Core Java
          主站蜘蛛池模板: 合山市| 沁阳市| 博湖县| 灵武市| 罗源县| 论坛| 名山县| 浦东新区| 洛隆县| 永定县| 祁阳县| 陆丰市| 成都市| 临武县| 含山县| 临猗县| 贡觉县| 北海市| 岱山县| 关岭| 贺兰县| 吉安县| 容城县| 上蔡县| 海安县| 新竹市| 剑河县| 忻州市| 武宣县| 南投县| 栾川县| 宽甸| 通化市| 永丰县| 丰都县| 和静县| 大同县| 辽阳市| 闻喜县| 巴林右旗| 图们市|