none
[VB2005]請問 Socket.BeginConnect 的問題 RRS feed

  • 問題

  • 各位大大好,
    因為 code 太長, 沒辦法貼上來, 大概敘述流程, 大致如下,
    1. 有一個 udp socket 的非同步的 receive callback,
    2. 在裡頭 new 一個 delegate , 把 sub 帶到某 class , 用 delegate.invoke 去執行這個 sub,
    3. 這個 sub 裡 new 一個 socket, 用 beginconnect, <---- 到目前為止為同一個 thread,
    4. 之後這個 socket 的 connect callback function, 是另一個 thread,

    正常狀態下都 ok ....
    但在 1 ~ 3 步驟 重覆 40 ~ 50 次, 也就是 new 了 40 ~ 50 個 socket 去做 beginconnect,
    (因為都是同一個 thread, 所以這 40 ~ 50 次不是同時進行, 但間隔時間很短)
    有的時候正常, 有的時候會發生第 4 步驟的 connect callback function 跟 1~ 3 步驟是同一個 thread,
    也就是在第 4 步驟的 function 裡下中斷, 其 callstack 可以追到 第1步驟的 receive callback,

    請問是否有大大能夠幫忙解說一下可能發生這種情況的原因嗎?

    若有不詳盡的地方, 請大大提出, 小弟盡可能補上足夠的資訊,
    謝謝

    2009年3月6日 下午 12:19

解答

  • 你的意思我有點不懂..
    比如有一個UDP的訊息被這程式接收之後
    程式會同時發出多個TCP connection還是一個?
    基本上,如果以你的程式形式,我Block的地方會出現在UDP的BeginReceived之後
    並不是在TCP的BeginConnect之後
    直到TCP的BeginSend成功才會將Block解除
    當然也要撰寫一些Try Catch來避免出狀況卡死

    • 已標示為解答 LonghairPan 2009年3月12日 上午 04:51
    2009年3月10日 上午 01:25
    版主

所有回覆

  • UDP應該不需要先connect吧?
    不過照你的情形,是否在執行beginconnect時根本沒connect上對方
    出問題時有錯誤碼產生嗎?
    可以把beginconnect 的程序內容貼上來看看,也許比較容易找問題
    2009年3月9日 上午 06:48
    版主
  • 感謝大大的回覆,

    我的 UDP socket 並沒有 connect, 只是 bind 一個 port ,然後 beginreceive, 等 receive callback,
    上面沒說清楚, sorry, 第三步驟是 new 一個 TCP socket 去下 beginconnect
    2009年3月9日 上午 08:58
  • 我之前遇過類似的問題..
    提供給您參考
    先講這程式的走法
    這個程式基本上先啟動一個 TCP Listener的Socket
    listener Accept之後一旦進入Beginreceive後就會把這些資料丟到另外一個設備
    等設備回應之後,我就再用BeginSend把設備回傳的資料丟給原來Connect上的這一個Client Socket
    應該有點類似你的情形
    我後來發現,應該在Beginaccept 之後給它一個 ManualResetEvent 的WaitOne,最後在beginsend時候再Set回來
    不然它就會發生像你一樣的情形,有時候啥事都沒做就跑回來了...
    所以,你可以試著在UDP的BeginReceive後面給它一個wiatOne()
    ========================================
    我的程式碼在這部份的片斷大概是長這樣
     thisworkDone.Reset()  
     Dim acceptCallBack As New AsyncCallback(AddressOf AcceptHandler)  
     thisworkSocket.BeginAccept(acceptCallBack, AcceptState)  
     thisworkDone.WaitOne() 
    其中  thisworkDon是一個ManualResetEvent 類別的instance
    AcceptState是自訂的一個 Async State object
    (很多人都會用nothing,不過因為這程式傳來傳去的東西太多,所以就給了它這麼一的東西,基本上我也會把ManualResetEvent包在這Object裡以便傳來傳去)
    2009年3月9日 上午 09:40
    版主
  • 謝謝大大的回覆, 小弟也想過用這方法,
    但會使用 BeginConnect 方法, 正是因為不想要這個 thread 在這裡 block 住,

    因為可能會在很短的時間內要 new 上百個 tcp socket 去 connect,
    目前有想到利用 threadpool 開 thread 做同步的 connect , 但還沒有實驗過, 不知道是否可行
    2009年3月9日 下午 04:41
  • 你的意思我有點不懂..
    比如有一個UDP的訊息被這程式接收之後
    程式會同時發出多個TCP connection還是一個?
    基本上,如果以你的程式形式,我Block的地方會出現在UDP的BeginReceived之後
    並不是在TCP的BeginConnect之後
    直到TCP的BeginSend成功才會將Block解除
    當然也要撰寫一些Try Catch來避免出狀況卡死

    • 已標示為解答 LonghairPan 2009年3月12日 上午 04:51
    2009年3月10日 上午 01:25
    版主
  • 謝謝大大的回覆,
    目前小弟稍微調整了 lock 的部份, 把 beginconnect 拉到 mutex 的區段之外, 即使 call stack 在同一個 thread , 也不會再 deadlock,
    因為要 blocking 的話, 要動到的部份滿多的, 所以只好暫時按下, 等以後比較有時間再來改, 謝謝
    2009年3月12日 上午 04:51