線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:4347
推到 Plurk!
推到 Facebook!

使用Socket連續傳輸問題

缺席
pdcmg
一般會員


發表:3
回覆:22
積分:20
註冊:2004-11-09

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-11-18 13:18:06 IP:220.135.xxx.xxx 未訂閱
我做了一個Client-Server的聊天程式~ 用的是BCB內建的TdServerSocket和ClientSocket 我做了一個功能就是~Server端有個listbox會記錄目前連上線的Client電腦~ 要Client電腦數一有更動~(connect or disconnect) Server就會以廣播的方式把更新過的listbox的內容傳給各個Client 但是用for loop做此動作由於傳送速度太快~Client的顯示會有問題~ 我目前是以Sleep來解決~但是發現一但在線上的Client端數量不同~所需要Sleep的時間也不同(因為資料量不同)...請問各位高手有沒有辦法不用Sleep或延遲發送的方式解決這個問題(因為效率實在不好!) 謝謝各位~ 以下是我部分程式碼:    
//------------------------------------Server端---------------------------------------------
void __fastcall TForm1::ServerSocket1ClientConnect(TObject *Sender,
      TCustomWinSocket *Socket)
{       AnsiString szRemoteIP=Socket->RemoteAddress;
   AnsiString szRemoteHost=Socket->RemoteHost;
   AnsiString szSocketHandle=IntToStr(Socket->SocketHandle);
   AnsiString szClientList=szRemoteIP "," szRemoteHost "," szSocketHandle;
   int i=ListBox1->Items->IndexOf(szClientList);
   if(i<0)
   {
      ListBox1->Items->Add(szClientList);
   }
   Label3->Caption=ListBox1->Count;       if(ListBox1->Count<=0) return;
   if(ListBox1->ItemIndex<0) ListBox1->ItemIndex=0;           for(int j=0; jCount; j  )
   {
      TStringList *sl=new TStringList;
      sl->CommaText=ListBox1->Items->Strings[j];
        ServerSocket1->Socket->Connections[j]->SendText("0|Clear");            for (int k=0;kCount;k  )
        {
          Sleep(50);
          ServerSocket1->Socket->Connections[j]->SendText("1|" ListBox1->Items->Strings[k]);
        }
     delete sl;
   }    }
//---------------------------------------------------------------------------    void __fastcall TForm1::ServerSocket1ClientDisconnect(TObject *Sender,
      TCustomWinSocket *Socket)
{
   int maxcount;
   AnsiString szRemoteIP=Socket->RemoteAddress;
   AnsiString szRemoteHost=Socket->RemoteHost;
   AnsiString szSocketHandle=IntToStr(Socket->SocketHandle);
   AnsiString szClientList=szRemoteIP "," szRemoteHost "," szSocketHandle;
   int i=ListBox1->Items->IndexOf(szClientList);
   maxcount=ListBox1->Count;
   if(i>=0)
   {
      ListBox1->Items->Delete(i);
   }
   Label3->Caption=ListBox1->Count;       if(ListBox1->Count<=0) return;
   if(ListBox1->ItemIndex<0) ListBox1->ItemIndex=0;       ListBox1->Refresh();       for(int j=0; jCommaText=ListBox1->Items->Strings[j-1];}
      else
      {sl->CommaText=ListBox1->Items->Strings[j];}          ServerSocket1->Socket->Connections[j]->SendText("0|Clear");            for (int k=0;kCount;k  )
        {
          Sleep(50);
          ServerSocket1->Socket->Connections[j]->SendText("1|" ListBox1->Items->Strings[k]);
        }          delete sl;
     }
   }
}    //------------------------------------Client端---------------------------------------------
void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
      TCustomWinSocket *Socket)
{
        int mode;
        AnsiString as="";
        TStringList *sl=new TStringList;
        sl->Delimiter='|';
        sl->DelimitedText=Socket->ReceiveText();
        mode=StrToInt(sl->Strings[0]);
        switch(mode){
                case 0:
                {
                  ListBox1->Clear();
                  break;
                }
                case 1:
                {
                  ListBox1->Items->Add(sl->Strings[1]);
                  break;
                }            }
        delete sl;    }
發表人 - pdcmg 於 2004/11/19 00:31:39 發表人 - pdcmg 於 2004/11/19 00:34:13
geniustom
版主


發表:100
回覆:303
積分:260
註冊:2003-01-03

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-11-22 02:57:46 IP:219.68.xxx.xxx 未訂閱
最近太忙了,所以一直沒時間回答你的問題 我今天花一個5個小時的時間寫了 http://delphi.ktop.com.tw/loadfile.php?TOPICID=18822894&CC=420966 裡面有原始檔跟執行檔,不過是DELPHI的拉,你應該看的懂 裡面有 class="code"> 1..你的SERVER端收到的訊息都寫在SocketRead裡,其實這樣不太好,因為 A..你的SERVER端只有一個PROCESS,收訊息,廣播,全都靠1個THREAD來處理,人數少,純聊天室還 沒差,不過如果人數有點多,又要傳檔時,你的SERVER鐵掛 B..我覺得比較好的方式是自己寫一個THREAD,當收到一筆資料時,就建立一個THREAD,並把訊息 丟給她,然後你的SERVERSOCKET只要負責收訊息,封包的處理跟判斷就交給THREAD,THREAD處 理完的時候,會將自己終結,既好寫,效能又好 2..封包的間隔可以用數字,但不要用特殊符號,尤其是看了你分隔的方式,感覺怪怪的 你看看我的LIB.PAS裡面的封包定義,都是照規格走,CHR(13)跟CHR(27)都算是控制碼 不會有中文字元或英文字元相衝 3..斷線的時候最好是由CLIENT 送出斷線封包,SERVER收到之後,從SERVER斷,不要從CLIENT斷 因為這樣SERVER會視為TIMEOUT而斷,ActiveConnections就不會即時的變動,你有一些需要 ActiveConnections的東西就會出錯(這個你看我的CLEINT斷線部份的程式碼就可以了解) 以上這幾種方式我之前用在我的專題(線上遊戲),效能很好,錯誤率幾乎等於0 還有,這邊有用BCB傳檔的範例,你若完成了,就可以試試 http://delphi.ktop.com.tw/topic.php?topic_Id=25914 我寫的這支程式,有試過不同的電腦,完全沒問題,不會LOSE,速度也快,穩定 你跟賴肥好好試看看吧..加油囉 <> <> <> < > <> < class="code"> =程式是一種藝術 也是訓練自己的分析規劃= =是段落分明 或是雜亂無章= =是一言以敝 或是廢話連篇= =是一目了然 或是艱深難懂= 體會這份藝術 您會了解另一份喜悅與成就
sky810675
一般會員


發表:5
回覆:23
積分:5
註冊:2006-07-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-07-26 10:10:59 IP:140.128.xxx.xxx 訂閱
http://delphi.ktop.com.tw/loadfile.php?TOPICID=18822894&CC=420966
http://delphi.ktop.com.tw/topic.php?topic_Id=25914

這2個載點都不能下載說~!請大大幫我看一下!^^

cuteysc
初階會員


發表:16
回覆:37
積分:35
註冊:2003-05-28

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-08-15 04:07:01 IP:61.217.xxx.xxx 訂閱
這段程式根本大有問題

首先你應該定義一個資料結構是專門送給 Client 通知有誰上線了, 由 Client 自行增加這位 User ID, IP 等資訊
就算不是資料結構, 好歹你也定義一個 Command Strings

比如 Server 送出一個字串 AddUser:用戶ID,202.133.245.86

Client 收到字串 AnsiPos("AddUser:")==1 的時候, 開始分割:後面的 ID 和 , 後面的 IP

擷取出來再 ListBox1 新增, 這樣才是正確的方法, 而定義離線則可以用 DelUser:用戶ID

Client 收到字串 AnsiPos("DelUser:")==1 的時候, 開始分割:後面的 ID, 然後判斷自己的 ListBox1 裡面有無此 ID, 有則 Delete()

不然 Server 肯定忙翻, 每一個用戶的進出就要傳送多達 User*data 的資料量

而且 Server 最忌諱的就是 Sleep() 這個函式, 因為會因為這個函式而降低你 Server 處理的效能
編輯記錄
cuteysc 重新編輯於 2007-08-15 04:09:12, 註解 無‧
T610
一般會員


發表:0
回覆:1
積分:0
註冊:2005-04-03

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-10-03 00:57:53 IP:220.141.xxx.xxx 訂閱
請問那位仁兄 有  geniustom 所提之 LIB.PAS UNIT2.PAS UNIT1.PAS
關於 Socket連續傳輸問題的壓縮檔
原始的這個下載網址 已無法下載
http://delphi.ktop.com.tw/loadfile.php?TOPICID=18822894&CC=420966

先謝囉!
系統時間:2024-04-20 2:17:14
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!