none
BeginAccept與Thread.Sleep的問題 RRS feed

  • 問題

  • 各位大俠~小弟又來了~~
    又是Socket的問題~
    最近使用非同步的方式來寫
    突然有個疑問想請教各位的看法
    就是小弟宣告一個socket並開一個新的執行緒去跑
    在監聽等待client連線這裡
    假設連線數設為10個用戶
    我是用迴圈一口氣開10個BeginAccept放著等
    還是用遞迴一次開一個~有人連再呼叫自己開一個
    還是說兩種方式都一樣~沒差別??
    小弟是希望可以做到當有人離線,程式會自動再開新的BeginAccept迎接新用戶
    還有Thread的Sleep的該如何用呢
    之前有位大大建議我
    如果我有在一個Thread裡用無限迴圈在跑
    最好加個Sleep
    不過小弟不太懂
    不是說不知道怎麼寫這語法,而是不知道其原理跟正確用法??
    看過一些程式裡面也都會有~不過卻不知道為什麼要加這個?
    有什麼好處嗎?不加會怎樣呢??
    麻煩各位大俠了~改天小弟會請大俠們吃漢堡包

    2008年10月18日 上午 11:14

解答

  • 你要看工作管理員的 CPU 使用率才能發現差異。

     

    Sleep 用途可以看這邊:

    http://tlcheng.spaces.live.com/Blog/cns!145419920BFD55A7!1640.entry

     

    WaitOne 有多載,先說原型有兩個參數的,算是 Sleep 的進階版,Sleep 一睡,就要睡到指定時間才醒來,WaitOne 可以指定睡覺的時間,睡覺期間事件發生,就會立刻醒來,就可以立刻處理,不像 Sleep 必須等到時間滿了才能處理。

     

    無參數的 WaitOne() 則是睡到有事件才醒來。

     

    所以效果是可以把 CPU 使用率降低,從畫面上看不出來,CPU 太快也看不出來。
    2008年10月22日 上午 11:35

所有回覆

  • HI,

     

    以下有使用多執行緒的Socket程式範例:

    http://www.drdobbs.com/windows/184405147

     

    tihs

    2008年10月18日 下午 01:39
  • 真是太棒了~~
    如果有中文的就更棒了
    小弟看了一下~發現他的範例是C#的樣子噎
    跟VB有通用嗎?
    麻煩大大了
    2008年10月18日 下午 03:18
  • 線上手冊就有了:

    ms-help://MS.MSDNQTR.v80.cht/MS.MSDN.v80/MS.VisualStudio.v80.cht/dv_fxnetwork/html/13624cd3-f5c5-4950-8cda-31273b1fa6d1.htm

    非同步伺服器通訊端範例

     

    ms-help://MS.MSDNQTR.v80.cht/MS.MSDN.v80/MS.VisualStudio.v80.cht/dv_fxnetwork/html/813489a9-3efd-41b6-a33f-371d55397676.htm

    使用非同步伺服器通訊端

     

    ms-help://MS.MSDNQTR.v80.cht/MS.MSDN.v80/MS.NETDEV.v10.en/dndotnet/html/progthrepool.htm

    Programming the Thread Pool in the .NET Framework

     

    不過我想你是觀念錯誤了。

    Accept 是開始在聆聽的位置接受連入。

    除非你開 10 個 port ,否則事不能同時有 10 個執行緒在同一個 port 接受聆聽。

     

    我是用一個物件集合來存所有的連線中的集合:

    Dim connectedSockets As ArrayList

     

    所以可以在你做下一次 BeginAccept 前,判斷集合物件裡面有幾個物件。

     

    我會定時掃描這個集合,有意外斷線的就主動移除,這樣資源就不會卡太久。

    2008年10月18日 下午 05:33
  • 小弟實驗了大大說的範例後
    又有一些問題~
    使用非同步是不是就能夠不需要在配合使用Thread了?
    主執行緒不是就不會為了等資料而停住~配合CallBack就可以處理
    所以說小弟是不是應該用遞迴的方式去設計讓程式可以持續監聽~主程式又不會停掉

     

    Code Snippet

    Dim Saki As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
    Dim ipPort As New IPEndPoint(IPAddress.Any, 36000)
    Dim max As Integer = 3

    Dim connectedSockets As ArrayList

     

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

     

        Saki.Bind(ipPort)
        Saki.Listen(1)
        Saki.BeginAccept(New AsyncCallback(AddressOf test), Saki)

     

    End Sub


    Private Sub test(ByVal val As IAsyncResult)
        MsgBox("ok")

        Dim clientSaki As Socket = CType(ar.AsyncState, Socket)

        connectedSockets.Add(clientSaki)

        If max>0 then

            max -= 1
            Saki.BeginAccept(New AsyncCallback(AddressOf test), Saki)

        end if

    End Sub

    這樣就可以持續監聽~直到設定人數滿了

    不過...這樣子...我想應該是能從ArrayList去指定要傳資料給誰

    不過我該怎麼寫function去監聽他們有沒有傳資料來呢??

     

    還有就是我有再範例裡看到

    Public Shared allDone As New ManualResetEvent(False)

    allDone.Reset()

    allDone.WaitOne()

    我看他是放在while裡~~一開始以為是用來讓while暫停用的

    不過想想好像也不太合理

    想請問一下這是用來做什麼的?? MSDN使用的詞彙很有深度~看不太懂...

    再麻煩一下大俠們了

    2008年10月21日 上午 08:42
  • 線上手冊中文就寫的很清楚了:

     

     

    ms-help://MS.MSDNQTR.v80.cht/MS.MSDN.v80/MS.NETDEVFX.v20.cht/cpref14/html/M_System_Net_Sockets_Socket_BeginAccept_1_2bb042b2.htm

    Code Snippet

    Socket.BeginAccept 方法 (AsyncCallback, Object)

    ...

    備註

    連接導向通訊協定可以使用 BeginAccept 方法,以非同步方式處理連入的連接嘗試。非同步方式接受連接將讓您能夠在不同的執行緒內傳送和接收資料。在呼叫 BeginAccept 方法之前,您必須呼叫 Listen 方法來聆聽輸入的連接要求,並將它排入佇列。

    您必須建立實作 AsyncCallback 委派 (Delegate) 的回呼 (Callback) 方法,並傳遞其名稱給 BeginAccept 方法。若要這樣做,最起碼必須透過 state 參數,將接聽中的 Socket 物件傳遞至 BeginAccept。如果您的回呼需要更多資訊,則可以建立小型的類別來儲存 Socket 和其他必要的資訊。透過 state 參數將這個類別的執行個體傳遞至 BeginAccept 方法。

    您的回呼方法應該叫用 EndAccept 方法。當應用程式呼叫 BeginAccept 時,系統會使用不同的執行緒執行指定的回呼方法,並封鎖 EndAccept,直到擷取了暫止連線為止。EndAccept 將會傳回新的 Socket 物件,可供您用於與遠端主機傳送和接收資料。您無法使用這個傳回的 Socket 接受任何來自連接佇列的額外連接。如果您想要原始執行緒在呼叫 BeginAccept 方法之後進行封鎖,請使用 WaitHandle.WaitOne。當您要讓原始執行緒繼續執行時,請在回呼方法中 ManualResetEvent 上呼叫 Set 方法。如需撰寫回呼方法的詳細資訊,請參閱回呼範例。

     

     

    所以只是你不需要寫 New Thread 相關的程式碼,但不表示是用單緒的。

     

    你要問範例的程式碼,請明確列是哪個網址,我給你的參考不只一個網址。

    2008年10月21日 上午 10:20
  • 小弟突然有些頭緒了~~已經大概有個想法了

    樓上的大大拍謝~是ms-help://MS.MSDNQTR.v80.cht/MS.MSDN.v80/MS.VisualStudio.v80.cht/dv_fxnetwork/html/13624cd3-f5c5-4950-8cda-31273b1fa6d1.htm

    裡面AsynchronousSocketListener class裡的Main 中有一個while

    是想問裡頭的

    Public Shared allDone As New ManualResetEvent(False)

    allDone.Reset()

    allDone.WaitOne()

    它的功用是什麼?

    我有加跟沒加好像沒什麼不同?

     

    還有Thread的sleep~~有加沒加好像也沒什麼感覺?

    加這個sleep主要會有什麼功效~專治什麼??

     

    不好意思啦~問太多

    2008年10月22日 上午 10:35
  • 你要看工作管理員的 CPU 使用率才能發現差異。

     

    Sleep 用途可以看這邊:

    http://tlcheng.spaces.live.com/Blog/cns!145419920BFD55A7!1640.entry

     

    WaitOne 有多載,先說原型有兩個參數的,算是 Sleep 的進階版,Sleep 一睡,就要睡到指定時間才醒來,WaitOne 可以指定睡覺的時間,睡覺期間事件發生,就會立刻醒來,就可以立刻處理,不像 Sleep 必須等到時間滿了才能處理。

     

    無參數的 WaitOne() 則是睡到有事件才醒來。

     

    所以效果是可以把 CPU 使用率降低,從畫面上看不出來,CPU 太快也看不出來。
    2008年10月22日 上午 11:35
  • 瞭解了~~
    非常感謝大俠抽空幫助我了解更多知識~
    只會for跟if真的不算是會寫程式呢~要會的東西太多了
    2008年10月22日 下午 04:07