none
關於 Socket 與 Thread 的問題 RRS feed

  • 問題

  • 以下是我想做到的功能 用 socket 與 thread 來做

    1.  Client 端會向server 端建立連線

         a.) server 端 會去接收外部的資料 然後 主動 將資料 push 給Client 端程式

         b.) 因為 a 的需求 我必須記住 所有 連上 server 的client 但 送出資料時 又要 塞選 要送給哪些client

    2.  此server 有回補功能 就是說  若 client 送出一個要求  就會將 他送出要求前的資料全部回補送出

        可是這會遇到一個問題就是  若在回補中間有遇到  新資料進來  那這樣 會不會產生衝突  新資料會掉的問題

     

    以上 是我對 這個  server 的一些想法    有沒有  給我一個方向

    因為  我找了 許多範例都很難同時解決  1  ,  2 的問題 

    請大家幫幫忙 

    2008年7月28日 上午 04:54

解答

  •  璉璉 寫信:

    比如說宣告區有個

    Public ClientList As Collection

    在這行之下加入:

    Code Snippet

    Dim clientSocket As Socket = tcpListener.AcceptSocket()

     

    ClientList.Add(clientSocket, "代號比如說IP")

     

    Socket 關閉時移除從 ClientList 移除即可。

     

    要用時,就

    ClientList("代號比如說IP")

    就可以取出了。

     

    這是基本變數的應用,如果不知道的話,先重看一遍吧。

     

    謝謝您的回應

    這個方法  我有個問題 就是  

    Public ClientList As Collection

    這個應該在哪裡宣告 才能讓  server 端要 push 資料時能拿到 這個 變數

    因為 若在 ClientListener Class  中宣告 就是 每個 thread 都會有一個 ClientList 的物件

     

    再請您幫幫忙囉

     

     

    2008年7月28日 上午 07:15
  • 另外先前版上討論過的範例:

    如何攔截所有封包程式

     

    2008年7月28日 上午 07:33
    版主

所有回覆

  • 1 的部分只要不斷線就可以了,若有身分識別的問題,建一個 Collection 就可以了,除非是送資料很密集,否則通常是反過來處理,來節省頻寬,client 定時回報自己的 IP ,等到需要資料的時候才由 Server 連到 client 端,所以 client 端本身要 Listen 。

     

    2 的部分請說明清楚為何會掉資料,通常是你資料排程邏輯錯誤問題才會掉資料。

    2008年7月28日 上午 06:17
    版主
  •  璉璉 寫信:

    1 的部分只要不斷線就可以了,若有身分識別的問題,建一個 Collection 就可以了,除非是送資料很密集,否則通常是反過來處理,來節省頻寬,client 定時回報自己的 IP ,等到需要資料的時候才由 Server 連到 client 端,所以 client 端本身要 Listen 。

     

    2 的部分請說明清楚為何會掉資料,通常是你資料排程邏輯錯誤問題才會掉資料。

     

    首先

    針對 (1)  我自己有參考以下的sample code 可是 我不知如何去把 連進來的 client 存入  arraylist中  然後 當 Server 有另外一個 thread 在接收外部資料時 來指定送給特定的Client  資料

                請給點意見

            (2) 就是  比如   Client A 跟  server 要回補資料 就是 此時點前 的資料 我會記錄在 DataTable中  在  回補期間 若有新資料進來  server 同時也會 把資料送給 Client A

                 這時會不會 有新資料漏掉的問題  因為  還在回補  可是 又有新資料 

            因為 還在 規劃階段  很多東西 會想很多 請您幫幫忙

     

    Code Snippet

    'ServerSocket

    '----------

    Imports System.Net
    Imports System.Net.Sockets
    Imports System.Threading

    Public Class ServerSocket
      Public Shared Sub Main()
        Try
          Dim serverIP As IPAddress = IPAddress.Parse("127.0.0.1")
          'Dim serverIP As IPAddress = Dns.Resolve("localhost").AddressList(0)

          ' Port = 80
          Dim Port As String = "80"

          Dim tcpListener As New TcpListener(serverIP, Int32.Parse(Port))

          tcpListener.Start()

          Console.WriteLine("Server started at: " + serverIP.ToString() + ":" + Port)

          Dim lc As New ListenClient(tcpListener)
          Dim serverthread As New Thread( _
              New ThreadStart(AddressOf lc.ServerThreadProc))
          serverthread.Start()

        Catch ex As Exception
          Console.WriteLine(ex.StackTrace.ToString())
        End Try
      End Sub
    End Class 

     

     

    Code Snippet

    'ListenClient  Class

    '------------------------------------------------------------------------

    Imports System.Threading
    Imports System.Net
    Imports System.Net.Sockets

    Public Class ListenClient
      Private tcpListener As System.Net.Sockets.TcpListener
      Private clientSocket As System.Net.Sockets.Socket

      ' 建構函式
      Public Sub New(ByVal tcpListener As System.Net.Sockets.TcpListener)
        Me.tcpListener = tcpListener
      End Sub

      Public Sub ServerThreadProc()
        Do While True
          Try
            Dim clientSocket As Socket = tcpListener.AcceptSocket()

            Dim clientInfo As IPEndPoint = CType( _
                clientSocket.RemoteEndPoint, _
                IPEndPoint)
            Dim serverInfo As IPEndPoint = CType( _
                tcpListener.LocalEndpoint, _
                IPEndPoint)

            Console.WriteLine("Client: " + clientInfo.Address.ToString() + ":" + clientInfo.Port.ToString())
            Console.WriteLine("Server: " + serverInfo.Address.ToString() + ":" + serverInfo.Port.ToString())
          Catch ex As Exception
            Console.WriteLine(ex.StackTrace.ToString())
          End Try
        Loop
      End Sub
    End Class

     

     

    2008年7月28日 上午 07:01
  • 比如說宣告區有個

    Public ClientList As Collection

    在這行之下加入:

    Code Snippet

    Dim clientSocket As Socket = tcpListener.AcceptSocket()

     

    ClientList.Add(clientSocket, "代號比如說IP")

     

    Socket 關閉時移除從 ClientList 移除即可。

     

    要用時,就

    ClientList("代號比如說IP")

    就可以取出了。

     

    這是基本變數的應用,如果不知道的話,先重看一遍吧。

    2008年7月28日 上午 07:07
    版主
  • 2 的部分隨便找個聊天室的範例都可以

     

    隨時都有人在寫訊息,聊天室會把訊息送出,所以看個人規劃,只要邏輯沒問題都不會掉資料。

     

    2008年7月28日 上午 07:09
    版主
  •  璉璉 寫信:

    比如說宣告區有個

    Public ClientList As Collection

    在這行之下加入:

    Code Snippet

    Dim clientSocket As Socket = tcpListener.AcceptSocket()

     

    ClientList.Add(clientSocket, "代號比如說IP")

     

    Socket 關閉時移除從 ClientList 移除即可。

     

    要用時,就

    ClientList("代號比如說IP")

    就可以取出了。

     

    這是基本變數的應用,如果不知道的話,先重看一遍吧。

     

    謝謝您的回應

    這個方法  我有個問題 就是  

    Public ClientList As Collection

    這個應該在哪裡宣告 才能讓  server 端要 push 資料時能拿到 這個 變數

    因為 若在 ClientListener Class  中宣告 就是 每個 thread 都會有一個 ClientList 的物件

     

    再請您幫幫忙囉

     

     

    2008年7月28日 上午 07:15
  • Module

    這是變數生命周期的基本觀念,你也要重念了。

     

    2008年7月28日 上午 07:17
    版主
  •  璉璉 寫信:

    Module

    這是變數生命周期的基本觀念,你也要重念了。

     

     

    真是慚愧  

    請你在開示 一下  module  的一些觀念 或者 網站

    我自己有去google  查一下  沒有很直接的說明

    因為  以前寫 都是 用class 所以 對module 的觀念 很弱

     

    之後 我是要用 winform  來開發這個系統 

     

    2008年7月28日 上午 07:28
  • ...

    用 Google 幹嘛?直接看線上手冊 Module 的說明即可。

     

    2008年7月28日 上午 07:31
    版主
  • 另外先前版上討論過的範例:

    如何攔截所有封包程式

     

    2008年7月28日 上午 07:33
    版主
  • 首先很謝謝大家的回應  我已大致把 Socket 加 thread 的架構implement出來

     

    但對於第二點  我還是挺擔心的

    我先說說  這個案子的狀況

    我的  Server 端 會去接收外部傳進來的資料  然後 我會將 這些資料 Push 給  有訂閱的Client端

    這些資料  我還會存在一個DataTable 中 

    為什麼呢

     

    因為  Client 端有一個功能  叫做回補資料的功能

    就是說  當Client 斷線時  重新連上  會傳給 Server 一個 回補的訊息

    這時  Server 會從 Data Table 中把  Client 端那個時點前  有訂閱的資料 Select 出來  一次回傳給 Client 端

     

    之前講的  若在  Select 期間 有新資料進來  怕會掉資料的問題  我用 Sync  的觀念來解決

    但現在 我怕的是  若 Client 要求  回補時  若這瞬間有資料 同時已經送給 Client 也 寫進 Datatable 中

    這樣 Client 端回補所select 出的資料也會送出   會收到 兩筆一樣的資料

     

    我目前能想到 就是 將每個  socket 有送出的  資料編號

    然後  在 DataTable 要回補時 用  not in(.....)  可是 資料越多 編號就越多

    反而會慢  

     

    有沒有  其它 更好的方法

     

    希望我描述的夠清楚  謝謝

     

     

     

     

     

     

    2008年7月30日 下午 03:11
  • 你的描述不夠清楚,請直接針對資料舉例。

     

    例如:

    1. 假設資料產生時間不會重覆

    2. 所有的產生資料的時間及值直接寫入資料庫

    3.送出時,由 client 發出最後一筆 tick ,查詢資料庫大於該 tick 的筆數送出,同時送出資料的時間 tick + value

     

    情境:

    a. 假設資料產生寫入資料庫後 client 才要求 -> 沒問題

    b. 資料產生瞬間尚未寫入資料庫 -> 下回 client 要求時 client 可收到

     

    另例:

    一般聊天室的時間不重要 (client 發出時間跟 server 收到時間不見得相同,順序上稍為有差異也沒關係),所以用資料庫自動編號當上面的 tick 就可以了,自動編號會依據進入資料庫的順序自動增加,就可以一直往下跑。

     

    你並沒有明確說清楚你的資料流程、先後順序、接收狀況,所以只能隨便談談。

    2008年7月30日 下午 03:24
    版主
  • 那我再試著描述一遍

    1. 資料產生時間 不會重覆 會依序從外部資料讀入 (ex:股票成交資料)

    2. 會將所有資料存入 Datatable 中 以利 select 速度

    3. 當Client Ap 登入時 會先跟server 訂閱 他要哪幾檔股票的成交資料

        此時Server 就會 收到資料時 去每個Socket 看是否有訂閱 然後 主動送給Client端

    4. 若 Client  要求  回補  它所訂閱的成交股票資料  會傳一個 訊息給Server

       這時server 會做以下動作

       a) 針對 此Client 所訂閱的股票 在這個時間點去 Select 出歷史資料 然後  送到Client端

       b) 因為 在 Select 那瞬間  可能會有新資料進來 同時也送出去給Client端了(參考3的說明)

           所以這時  Datatable 就會有這筆資料 也會被當成回補的資料

           這樣 Client 端就會收到兩筆

          

     

     

    2008年7月30日 下午 03:37
  • 1, 2, 3 都沒問題就不討論了。

     

    4 請說明你回補的邏輯。

    甲. 若是 client 端要求為時間範圍,資料回補是不會有重覆的,除非範圍錯誤。

    乙. 若是全部重新回補,那 client 應該清空歷史資料,也不會有重覆的問題。

     

    2008年7月30日 下午 03:46
    版主
  • 我是採取  乙  的方式   Client端在訂閱時 同時也要求回補以前的資料  所以 一開始是空的

    傳送管道有兩個:

    a.)  一般傳送 就是  收到資料就送給Client端

    b.)  要求回補 從 Datatable中 找出該時點的資料送給Client 端

     

    若有一筆資料 在 b 時產生 就會先送到 Client端  那麼 b的動作也會將此筆資料再送一次

     

    以上是我的想法  請再賜教 

    2008年7月30日 下午 04:06
  • 看不懂你的邏輯。

    2008年7月30日 下午 04:11
    版主
  • 對不起 我再努力讓你瞭解

     

    你就想說  今天  有一個 server 是在收 股示 成交回報的資料

    然後 每個Client 端都是 交易員  所 處理的股票都不一樣

    所以 訂閱的股票 成交回報都不一樣

     

    但 很不幸的 若 在  交易期間  這個交易員的電腦當機了

    要重新開Client 端的 AP 系統

    此時 會先重新跟 server 訂閱資料

    然後 再要求  回補 之前 那些成交的資料 不然 數據會不對

     

    但 成交資料 從交易所那邊 一直來 

    我是會記在 DataTable 中

    現在 擔心的是 若要求回補時  因為 有訂閱了 A 這檔股票 正好有成交回報 也送給了Client端

    回補資料中  也同時也記錄了這筆資料  又再送一次給Client端

    這種狀況 是很極端的  但  也要防  請問  有更好的方法嘛

     

    謝謝你的耐心  希望這次 你能瞭解 

    2008年7月30日 下午 04:21
  • :::假如要送A這檔股票至Client端,判斷Client端是否之前有送回補的Flag呢???是否可行???

     

    2008年7月31日 上午 03:58
  • 那要求就送兩個時間點啊~

    從開始的時間點到目前 Client 有的最舊資料的時間點之前,這樣資料就不會重覆了。

     

    2008年7月31日 上午 06:53
    版主