国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

Winsock控件,實現網絡點對點通信

2024-07-21 02:24:11
字體:
來源:轉載
供稿:網友
,歡迎訪問網頁設計愛好者web開發。網絡的階梯第二話:
使用winsock控件,實現網絡點對點通信
  blog出現在csdn,也就blog將不blog也。你會問為什么吧?無論你心里有沒有這個問號,但在我心里這是個句號!你又會問為什么嗎?好,不管你問不問。我決定,現在作答。但那種長篇大論的前因后果,請恕我無法一一羅列。我只能直接而又間接地說明,blog出現在csdn,也就blog將不blog也。
  使用vb,寫過網絡程序,沒試過winsock這個控件實在是遺憾(api高手除外)。我想沒有朋友有這種遺憾的...呵呵!因為,通過winsock控件,你可以把網絡通信簡化簡化再簡化。那是什么程度?可能就是10行代碼以內就行了那種(ide生成的隨外)!因為那只是網絡通信,而通信,僅僅就發送一條信息,對方收到了,顯示出來。可以算了吧?來看看:

  首先,窗口加載過程,我們寫上:
            '設置了第一個winsock控件進入等待
            winsock1.localport = 5052
            winsock1.listen
            '再來把第二個winsock控件連向第一個
            winsock2.connect "127.0.0.1", 5052

  好了,這時winsock1控件的connectionrequest事件觸發。我們寫上:
            if winsock1.state <> sckclosed then winsock1.close
            winsock1.accept requestid '接受連接

  就這樣就連上啦!簡單得很。再來:
            winsock1.senddata text1.text '把text1中的文本傳給對方

  當然了,你傳了數據給winsock2,那它的dataarrival事件也觸發了。
            dim strdat as string
            winsock2.getdata strdat '取得數據
            text2.text = strdat '在text2中顯示出來

  至此,一個使用winsock控件,實現網絡通信程序就完成了!哈哈哈,是不是覺得上當受騙了?這種點子,msdn里早有出賣了!蓋茲可真不是蓋的,竟然早早想到用msdn斷我財路!唉.難怪他比我富!

  我完成任務了?沒有,我要作的是《使用winsock控件,實現網絡點對點通信》。通信實現了,也是一個點對另一個點。可是,在普遍認識里,點對點并不是這么解釋的。怎么解?就是雙向通信吧!呵呵,但蓋茲始終比我富。這點子在msdn里又已經出賣了!

  不耐煩了吧?但要寫程序,就不能怕煩。如果你決定走這條路,那還有更煩更煩的等著你。喂,煩人,你能看得下去嗎?哈哈~!既然好點子全給蓋茲拿去賣了,那還有什么好說的?就如,比爾賣你一個空的數據表,可是不填上數據。它還是一個空的數據表,而不是數據表!但比爾是不能幫你填上適合你的數據的,所以,你要照著你現有的數據表,向空的數據表填上數據,再把源數據表刪了,那它就成了一個獨一無二的數據表了!

  我看你真的不耐煩了...你餓嗎?把鼠標蒸熟吃了頂一會吧!
  好,現在就讓我說一說,點對點通信應用里的一個重要程序...但這次,不會再像上面那樣,列出一行一行的代碼,然后告訴你添加到那里,然后怎樣...現在我要就“授人以漁”的政策,堅持“編程重思想”的方針;向“由淺入深”的路線,從“理解到認識”的哲學角度出發。解釋一下,通過winsock控件,在網絡上傳送文件的vb程序是怎么寫的!

  正如前面的例子一樣,用winsock控件通信,得分開客戶端與服務器,即:client、server(c/s)。但大家都知道,這僅是使用tcp協議必需要上演的一幕。而在udp里,并沒有明確的把c/s分開!但這樣概念要變模糊了。這在以后的話題里,我會再作解釋。今天我們的主角是tcp。
  上例中,那個循序漸進的步驟,大家體會到嗎?沒關系,現在來回顧一下。

服務器監聽5052端口。
客端連接到服務器的5052端口,就是服務器程序監聽的端口了!
由于有客戶連接,服務器程序那的winsock控件就觸發connectionrequest事件(說明見msdn)。
服務器接受了連接,客端程序的winsock控件會觸發connect事件,以表示連接上(例省略)。
連接上后,由服務器程序向客戶端程序發送數據。
數據到達客端,winsock控件觸發起客端程序的dataarrival事件提示,取得數據,顯示!
  整個流程就這樣,顯然很簡單了,不對嗎?呵呵!然后,我們得到這么一個流程表后。就要開始填空了。打開我們想發送的文件讀取數據給服務器發送。對方收到數據后,再寫回到文件!過程就這么個樣了!具體實現起來,還得要思考思考。好,現在我們就從一個用戶的角度出發去想吧!

  兩個winsock怎么連上我就不說了,反正蓋茲都已經比我富!那我們要傳文件,先得讓用戶選擇一個文件吧。然后就開始傳啰!好傳,慢著!客端怎么知道服務器要傳的是什么類型的文件呢?好!有了這個想法,我們在用戶點擊服務器程序傳送文件按扭的時候,獲取剛才用戶選擇的文件的名字吧。要傳過去了?還是不行,如果我們這個程序是聊天+傳文件的話,那不是很混亂了?嗯,給這個信息一個名字吧!就叫:“send”怎樣?好,是個很有霸氣的名字~大家用過qq之類的聊天軟件傳文件都知道,qq會先詢問接收方是否接收xxxx.xxx的文件!那我們就模仿一下吧,把傳送命令和文件名設置成:"send 文件名",這樣的一個格式。然后用winsock的senddata方法傳給對方。

  那就去了客戶端編寫代碼啰:
  好,當收到這條命令,我們從前4個字得出,對方要傳文件過來了!也沒什么好寫的,就彈個msgbox出來說,對方要傳xxxx.xxx給你,你愿意接收嗎?好,當用戶把保存路徑確定下來了,然后在這樣的路徑里,創建一個這樣的文件,以備接收到數據時寫入。我們現在就得返回一條信息給服務器那,就叫:"iliefly "吧!表示確認接收。

  又轉回來服務器那寫代碼了:
  收到接收確認信息,我們開始進行讀文件操作了!把文件打開,聲明一個byte數組。把打開的文件數據全讀入到這個數組里。哈哈~不就成了嗎?那傳過去試試...

  客戶端開始接收到數據了:
  嘿,糟糕,怎么會有數據類型錯誤呢?原來每當有數據到達客戶端,我們在dataarrival事件寫的代碼都執行了。還以為是命令或聊天內容呢!不行,要給它設置一個標記,用作記錄什么時候傳過來的數據是文件的的數據吧。用一個static的語句(見msdn)聲明一個靜態布爾的變量,當false的時候是我們命令或聊天內容,而true的時候就是文件數據吧!再改一改上一次在客戶端那寫的源碼,在答應接收之后,把這個布爾變量設為true!啊?問題又出來了!這時我想到,那什么時候才能把布爾變量設回false呢?倒,還是有問題!目光集中到服務器那里去...

  再回到服務器的代碼編輯框:
  有什么辦法讓客戶端知道什么時候傳完呢?發送命令?不行,那里會把命令寫入到文件的。連接關閉?更加不行,我還要聊天...嗯,要是讓客戶端知道傳過去的文件長度,不就可以確定什么時候是接收完了嗎?哈哈!行動,改一改傳送文件的命令為:"send 文件名 文件長度"。哦?太多空格啦,那樣對方解釋起來相當麻煩嘛,用instr?不行,要是文件名里有空格怎辦?不就又出錯了...還好,我們有split嘛(見msdn)。好,那得把命令用個特別的字符分開了!就vbnullchar吧(見msdn)!把命令改成:["send" & vbnullchar & 文件名 & vbnullchar & 文件長度]。傳給對方。(注:filelen函數)

  客戶端要修改代碼了:
  聲明一個動態字串數組,把split函數的返回值附給它,哈哈!下標0是命令,下標1是文件名,下標2是文件長度!爽了~把長度用模塊域變量保存著,以備計算什么時候收完吧!(注:val函數)

  繼續在客戶端那寫我們沒完的代碼:
  布爾變量為true,有數據到達。那就取得它的數據吧!可要注意接收到的數據類型哦,對面傳過來的不是字符串了,我們要指定類型為"vbarray + vbbyte"(見msnd關于getdata的說明),意思就是字節數組啦。當然,我們要定義一個字節數組才能接收嘛 dim bytearray() as byte。好,那剛才保存下來的長度就有用啦,總長度-當次收到的字節數=剩余字節數。當剩余字節數為0的時候,不就接收完了嗎?哈哈!不急,先來組織一下思路:數據到達,取得,保存到字節數組。用ubound函數(見msdn)得到字節數組的最大下標,但由于數組下標0也存著數據,但文件不是這么算啊,所以要算就得+1算!總長度 = 總長度 - ubound(bytearray) + 1 嘿,行了!

  趕快運行試試,找個50多mb的傳。呵呵,突然,鐺!“內存不足”暈!搞什么鬼啊,再看一下進程列表,哇!我的程序占用了60mb左右的內存!暈,什么回事啊?是不是那里出錯了?再重組一下思路:選擇文件,發送命令,當收到返回確認信息,打開文件,讀...讀???不會吧,我把文件整個讀入內存了,難怪難怪(其實不會發生這個錯誤的,因為windows有虛擬內存嘛!但的確,要把整個文件讀入內存再發送出去,有點讓系統難為啊)!得優化優化了。

  回到服務器代碼里進行優化:
  不能一次讀入這么多,那...分開來吧!一次傳送:8192個字節如何?好!就這樣吧。但不是每個文件的字節數都為8192的倍數,怎辦呢?嗯,作個計算。之前,我們不是得到了要傳的文件的長度?既然對方都可以計算什么時候收完,那我也可以計算什么時候傳完嘛!首先,確定一下,要傳的文件長度是不是比8192大。如果是,那我們就把文件長度-8192。然后定義個下標是8191的字節數組(因為數組下標0也可以存數據嘛,所以要-1),用get方法,讀取打開的文件數據來填充這個字節數組。然后傳過去...嗯?對方好像會收了啊,未達到文件總長度時,客戶端不會把布爾數組設回來的。但,這邊怎么知道什么時候可以傳下一筆數據呢?嗯~sendcomplete 事件——在完成一個發送操作時出現。好,就是這個了!我們在這邊也用文件長度為0時作為結束傳送的條件。如果不為0,那就再看看還沒傳的文件剩下多少,因為上面的計算已經-去了上次傳送的字節了,那現在的文件長度變量就是剩下字節的數量啦,再比較一下,是否比8192大。哈哈~不是就定義一個這么大小的字節數組,讀文件,送出!完成~[msgbox "傳輸完畢!", vbinformation, "⊙_⌒γ - server"]...
  但突然發現,原來sendcomplete事件,在我們把傳文件命令發出去之后也會觸發。那沒法子了,只好再定義一個布爾變量來確定什么時候是傳文件吧...

  至此,一個用winsock控件傳送文件的vb程序寫完了!呵呵,沒睡著吧?不過我快睡著了!好困,上一次睡覺的時間只有3小時!現在-_-#了...但得說明一下,上面提到的8192,并不是我隨便安上去的。這個在以后再作詳細說明吧!

  嗯,要做的事還沒完!好像我沒說為什么:“blog出現在csdn,也就blog將不blog也”哈哈~其實這篇東東已經說得很清楚了!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 祁门县| 武城县| 车险| 防城港市| 镇原县| 资源县| 库尔勒市| 富顺县| 杭锦旗| 昭平县| 开封市| 荔波县| 大悟县| 北碚区| 理塘县| 无锡市| 正蓝旗| 台江县| 炎陵县| 罗定市| 清远市| 乌兰县| 通山县| 泸西县| 乾安县| 天门市| 全椒县| 崇明县| 永泰县| 嘉荫县| 嘉定区| 徐汇区| 游戏| 盐津县| 衡阳市| 永靖县| 绍兴市| 芜湖市| 郓城县| 永安市| 高尔夫|