2013-03-15 45 views
1

假設我有一個選擇循環,打開一些打開的連接,我將讀取它,並且每個連接都附加了狀態機,用於解析通過線路傳遞的一些內容,正確的事。假設其中一個連接c已準備就緒,並且選擇循環將其交給狀態機m進行處理。我們想從連接中讀取10個字節,我們將使用readpartial。不幸的是,只有6個字節已經給我們,所以m讀取6個字節並取消阻止。下一次循環遞給我們c它有11個字節。 m仍處於上次選擇循環遞給我們的c的任何狀態,並且知道它需要再讀取4個字節,因此它使用readpartial(4)讀取這4個字節,使用現在處於這種狀態的那10個字節進行某種副作用操作其緩衝區並轉移到新的狀態。 m仍持有該連接,因此此時它可以解除阻止環路或開始執行新狀態指定的操作,其中一個操作可能涉及readpartial。在這種情況下,正確的做法是繼續處理連接,因爲readpartial不會阻塞。但假設操作的順序是:接收6個字節,讀取6個字節&解鎖,接收4個字節,讀取4個字節&做一些事情。在這種情況下,沒有什麼可以讀取的,所以如果狀態機已經決定在連接上調用readpartial,那麼它將阻塞選擇循環,這是不合需要的情況,並且在這種情況下正確的事情將是狀態機器解鎖並等待選擇循環再次出現。用nio4r選擇循環的紅寶石套接字

如果我不想阻塞選擇循環,也不想在連接緩衝區中保留字節,那麼解決這個問題的正確和有效的方法是什麼?我已經瀏覽了Ruby的Socket和IO API,並且找不到能夠告訴我是否有東西需要讀取的方法。​​是一個潛在的探索途徑,通過讀取單個字節然後將其放回,但在我的測試中它不像預期的那樣工作,即char = c.read_nonblock(1); c.ungetc(char); wire_data = c.read_partial(10)結果爲wire_data == char,即使連接緩衝區有更多在緩衝區中比char

回答

1

像往常一樣寫出問題,我幫助我看到了解決方案。我可以撥打​​,而不是在狀態機中調用readpartial。​​會拋出一個異常,如果沒有什麼可讀的,我可以抓住這個異常並取消阻止選擇循環。