對于sql server2000來說,打開sql server客戶端準備連接,當拉開服務器列表的時候,整個局域網所有的sql server服務器都被列出來了。
vb.net枚舉網絡中所有的sql 2000服務器
對于sql server2000來說,打開sql server客戶端準備連接,當拉開服務器列表的時候,整個局域網所有的sql server服務器都被列出來了。于是我發現,從我自己的機器(192.168.0.1)上從1434端口廣播(192.168.0.255)了這個udp包,然后,整個局域網中的sql server服務器都開始響應這個udp數據包,這時,我的客戶端能夠得到所有服務器信息。
這就是客戶端進行連接的過程:當客戶端連接到服務器時,應用程序請求連接遠端計算機,dbnetlib.dll 將打開到連接中所指定的計算機網絡名上的 udp 端口 1434 的連接。所有運行 sql server 2000 的計算機都監聽此端口。當一個客戶端 dbnetlib.dll 連接到該端口時,服務器將返回一個監聽服務器上運行的所有實例的數據包。對于每個實例,該數據包報告該實例正在監聽的服務器 net-library 和網絡地址。應用程序計算機上的 dbnetlib.dll 收到該數據包后,選擇在應用程序計算機和 sql server 實例上都啟用的 net-library,然后連接為此數據包中的 net-library 列出的地址。
通過1434端口傳輸特定的udp數據包,然后服務器開始回應,所有這些都是明文傳輸的,我們可以很容易探測一個ip地址的1434端口,獲得該ip地址上運行的sql server的相關信息。這些信息包括:主機名稱、實例名稱、版本、管道名稱以及使用的端口等。這個端口是微軟自己使用,而且不象默認的1433端口那樣可以改變,1434是不能改變的,呵呵,那么我們為了安全,去改變這個1433端口能起什么作用呢?
我們可以來捕獲這些數據報,可以發現,通過1434端口的數據非常簡單,客戶端僅僅簡單地發送了02一個字節出去。不過多次捕獲,發現有時候發送的是 03。于是我就用下面程序一個一個測試,發送其他數據。不過最后只有02、03、04有回應。看來這三種字節用來做sql server探測的。而且你可以發送 02 00 00,也可以發送 02 00 00 00 00等等都能夠得到sql server的回應,但是發送 02 03就不可以了。
詳細代碼:
imports system.net
imports system.net.sockets
imports system.net.sockets.socket
imports system.collections.specialized
public class getservers
 
 
    '采用udp協議 
private m_client as sockets.udpclient
 
 
    '廣播地址,表示整個網絡 
private strhost as string = "255.255.255.255"
 
 
    '廣播端口 
private intport as integer = 1434
 
 
    '要發送的數據,發送這個數據所有的sqlserver就會響應了 
private b() as byte = new byte() {&h2}
 
 
    '因為 send 里面有個死循環,這里用個定時器來處理超時間 
private withevents t as new timers.timer
 
 
 
    '發送數據出去 
function send() as arraylist
m_client = new udpclient
 
 
        '用來存儲獲取的sql列表 
dim atemp as new arraylist
 
 
        '發送的目標,廣播地址 
dim host as new ipendpoint(ipaddress.parse(me.strhost), me.intport)
try
'這里發送數據
m_client.send(b, 1, host)
 
 
            '下面開始讀取,因為網絡內sql server數量眾多,數據包一個一個的返回 
'所以這里循環處理了。
while true
 
 
                '開定時器 
t.interval = 1000
t.enabled = true
 
 
                '接收的字節數組 
dim br as byte() = m_client.receive(host)
dim a as system.text.encoding = system.text.encoding.default
 
 
                '用來存儲當前字符串 
dim s as string = ""
 
 
                '從第4個數字開始,前三個字符為非打印字符 
s = a.getstring(br, 3, br.length - 3)
console.writeline(s)
 
 
                '這里解析獲取的文本 
atemp.add(new sqlserver(s))
 
 
                '關閉 
t.enabled = false
end while
catch ex as exception
console.writeline(ex.message)
finally
m_client.close()
end try
return atemp
'console.writeline("檢查完畢。。")
end function
 
 
    '超時后強制結束網絡等待。 
private sub t_elapsed(byval sender as object, byval e as system.timers.elapsedeventargs) handles t.elapsed
'console.writeline("關閉。。")
m_client.close()
t.dispose()
end sub
end class
 
 
 
public class sqlserver 
'sql server解析類
'
'因為返回的字符串類似 name1;value1;name2;value2;name3;value3; ....
'而且不固定長度
'所以這里用namevaluecollection返回。
private nv as namevaluecollection
 
 
    sub new(byval str as string) 
nv = new namevaluecollection
dim a as string() = str.split(";")
for i as integer = 0 to a.length - 1 step 2
dim t as integer = i
nv(a(t)) = a(t + 1)
next
end sub
 
 
    '因為要添加到combobox,這里重載了一下tostring以顯示文本 
overrides function tostring() as string
return nv("servername")
end function
 
 
end class
 
調用代碼
 調用代碼
sub getsqlservers()
me.cursor = cursors.waitcursor
dim a as arraylist
dim g as new getservers
a = g.send()
for each c as sqlserver in a
me.cb_server.items.add(c)
next
me.cursor = cursors.default
    end sub
 
    sub getsqlservers() 
me.cursor = cursors.waitcursor
dim a as arraylist
dim g as new getservers
a = g.send()
for each c as sqlserver in a
me.cb_server.items.add(c)
next
me.cursor = cursors.default
    end sub
 
新聞熱點
疑難解答
圖片精選