現在有一個服務端主機,需要實時探測局域網主機(1000臺以內)的開關機狀態,并且需要和他們通信。現在的思路是:
服務端:安裝服務端軟體,有一個TServerSoket組件(stNonBlocking模式),負責和所有服務機通信,還有一個TIdICMPClient,周期性ping各客戶機IP
客戶機:安裝客戶機軟體,隨機啟動,有一個TClientSocke組件,主動連接TServerSoket。
現在的問題是:
1 服務端ping各客戶機不穩定,大部分時間能ping通,有時不能ping通;
2 TServerSoket的read事件中可能會有例外。
求老司機幫助啊。
uj5u.com熱心網友回復:
利用心跳,建立聯系。uj5u.com熱心網友回復:
我現在的做法就是這樣,只要客戶端啟動了,就每隔n秒給服務端發個訊息
uj5u.com熱心網友回復:
大哥,能夠給個聯系方式,我付費請教些問題,例如:
我在執行緒中使用 TIdICMPClient.ping 主機,但是不穩定,有時明明開機,卻ping不通。
也可以加我QQ: 306068056,謝謝了。
uj5u.com熱心網友回復:
你判斷的是開關機狀態,不是通不通網狀態,如果開機但是網不通呢,心跳包傳不過來就代表關機就行了啊uj5u.com熱心網友回復:
感謝兩位的回復。開始我的思路是雙管齊下:
1 服務端主動使用TIdICMPClient.ping探測各客戶機的開關機狀態(開機要及時知道,關機也要及時知道。現在會出問題:明明開機,在CMD下能ping通,我的程式卻報例外:Socket Erro 10040:Message too long,有的說是TIdICMPClient不支持多執行緒,有的說是Indy的bug,還沒找到解決辦法);
2 客戶端開機后自啟動,主動給服務端發心跳,獲取自己的最新狀態(程式需求,客戶端可能已經被預定,如果被預定,客戶端要跳出來全屏鎖屏,不讓別人用)。同時,服務端只要收到了客戶機的心跳,就證明客戶機肯定是開機的。
現在看來,第1條,服務端主動開多執行緒(每臺客戶機一個執行緒,根據IP)ping客戶機是多余的了。下面是我的ping方法,在執行緒里呼叫,還請指正。
{測驗IP地址能否PING通}
function ping(url: string): Boolean;
var
i: Integer;
rst: Boolean;
err: String;
icmpClient: TIdICMPClient;
begin
i:= 0;
rst:= False;
icmpClient:= TIdICMPClient.Create(nil);
icmpClient.ReceiveTimeout:= 500;
icmpClient.Host:= url;
icmpClient.PacketSize:= 1024;
//ABuffer := url+ StringOfChar(' ', 255);
while (not rst) and (i<3) do
begin
inc(i);
try
icmpClient.Ping();
Application.ProcessMessages;
if (icmpClient.ReplyStatus.FromIpAddress = url) then
begin
rst:= True;
end
else
begin
rst:= false;
sleep(10);
end;
except
on e: Exception do
begin
err:= e.Message;
//Socket Error # 10040 Message too long.是ping不通時的正常超時例外
if pos('10040',err)=0 then
Logger.Log(url+' Ping例外:'+ err);
rst:= False;
sleep(10);
end;
end;
end;
Result:= rst;
icmpClient.Free;
end;
uj5u.com熱心網友回復:
現在看第1步,服務端主動ping 也不算是多余的,因為可能出現 客戶端不隨機啟動,或者延遲幾分鐘啟動的情況。客戶機數量眾多(100--1000),不由我控制,我的客戶端程式是免安裝的,由別人放到客戶機上,設定開機啟動項。
uj5u.com熱心網友回復:
我也在做同樣的功能,我是調WINDOWS的API來實作PING的uj5u.com熱心網友回復:
建議在客戶端建立心跳,服務器接收心跳資訊。比如心跳3分鐘一次。服務器端處理:
1、建立一客戶端的串列,記錄IP和用戶名、心跳時間。
2、接收到的資料,對比客戶端的串列,如無就新增,有就更新心跳時間。
3、定時掃描客戶端的串列,心跳時間超過3分鐘未接收,確定下線,從串列中洗掉。
uj5u.com熱心網友回復:
建議用IdIPMCast,客戶端隔幾秒報告自己的狀態,報告關機的就是關機狀態,超時不報告的就是失聯uj5u.com熱心網友回復:
心跳是常用做法
uj5u.com熱心網友回復:
你是要探測局域網中某些IP的電腦是否開機,還是要檢測局域網內某些電腦上你的客戶端軟體是否運行,這兩者并不完全等同。如果是前者,不要用ping,因為防火墻設定可以不回應ping,可以用SendARP獲取對方的物理地址(MAC地址),如果成功則對方電腦是聯網的,為了防止vista或者之后的windows使用本地快取的ARP表,可以先DeleteIpNetEntry再SendARP。
如果是后者,客戶端軟體可以監聽一個埠,如果接收到特定的握手資料(自己定義),就回傳一個特定的回應,這樣服務端輪詢局域網內的IP,就可以知道哪些客戶端啟動了。
uj5u.com熱心網友回復:
感謝各位的回復,我試試 SendARP 方法。uj5u.com熱心網友回復:
另外可以考慮WebSocket連接試試,不過這個可能服務器壓力比較大!而且不過是那種方式并不能確定對方是關機,可能客戶端軟體關掉也會中斷通訊。這種情況下可以用telnet來判斷是否關機也可以。uj5u.com熱心網友回復:
有個應用層的協議叫SNMP。很多設備包括主機、服務器、交換機、路由器、列印機都支持該協議。通過這個協議,做trap能間隔向指定的IP地址發送狀態資訊。
通過該協議還能畫出網路中的拓撲圖出來。甚至得知交換機埠的狀態。
uj5u.com熱心網友回復:
這種應用最好采用 UDP 發個心跳包,根本不建立連接,超過多少時間沒心跳包就判為關機就可以了1000臺以上機器,如果TCP的話,你的交換機負荷就不少,UDP比較正道。
如果用 winsock 的話,這個 UDP 也不需要什么控制元件,直接用Winsock庫里的幾個函式就解決了
uj5u.com熱心網友回復:
自己用socket寫server和client,何必 TIdICMPClient。思路如下:
服務器server開啟埠一直偵聽,客戶端卡機及運行client,向服務器注冊并定時發送心跳包,同時自己也開啟埠偵聽,服務器端得到客戶端的注冊資訊之后,一直接收客戶端來的心跳包,如果超過多長時間沒有收到,可以反過去連接客戶端埠,或者ping客戶端也行【呼叫系統的ping簡單吧】。
當然,如果client太多,建議用短鏈接。
uj5u.com熱心網友回復:
一個月之前的帖子?這個版人氣好低。uj5u.com熱心網友回復:
9月份發的帖了。。。。
Delphi真是沒人氣。
uj5u.com熱心網友回復:
人氣靠大家!!!uj5u.com熱心網友回復:
我來加點人氣:范大師都八級了....
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/46065.html
標籤:網絡通信/分布式開發
