VFP 愛用者社區 首頁 VFP 愛用者社區
本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入

揭開 Winsock 的神秘面紗 (轉貼)

 
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區
上一篇主題 :: 下一篇主題  
發表人 內容
Ruey



註冊時間: 2003-03-12
文章: 1698
來自: tunglo

第 1 樓

發表發表於: 星期六 五月 24, 2003 4:49 pm    文章主題: 引言回覆

主題: 揭開 Winsock 的神秘面紗<轉載>
內容:在今天 TCP/IP 處理所有 Internet 上的通信流. 在局域網上也可以運行 TCP/IP.
我們可以利用這一點, 並在諸如 FTP, IRC, e-mail, WWW 或其他任何 Internet 標準類型的通信. 要達到這樣的目的, 需要使用包含在 Windows 中的一個 DLL, 也就是所謂的 WSOCK32.DLL 或相似的名字.
在使用 DLL 中的唯一問題, 直接的, 是我們將不得不控制和處理每一個函數的反應而且這將會造成額外的和不必要的開銷.
Windows 已經有一個 ActiveX 叫做 WINSOCK.OCX. 它使用與我們所需要的相同的 DLL, 並已經用方法和事件控制和處理了整個反應, 使它易於使用.
初識 ActiveX Winsock 控制項
方法 說明
Accept(requestID) 該方法用於接收一個特寫的連接. 它作為一個參數傳遞來處理請求.
Bind(LocalPort,LocalIP) 為 CDP 連接指定埠和本地 IP.
Close() 關閉伺服器和客戶之間的活動的連接.
GetData(Data,Type,maxLen) 用緩衝中的內容填充變數, 使其為空.
Listen() 物件等等連接.
PeekData(Data,Type,maxLen) 用緩衝中的內容填充變數, 但不清空緩衝.
SendData(Data) 發送資料到遠端電腦.

事件 說明
Close 當遠端電腦關閉當前連接時發生
Connect(Error) 與伺服器的連接成功後.
ConnectionRequest(requestID) 當遠端電腦發出一個請示時.
DataArrival(BytesTotal) 在從遠端電腦上接收到新資料時發生.
Error(number, Description, Scode, Source, HelpFile, HelpContext, CancelDisplay) 當發生後臺處理錯誤時.
SendComplete 資料發送完畢時發生
SendProgress(bytesSent, bytesRemaining) 在發送資料時.

屬性 說明
BytesReceived 返回到緩衝中的位元組數
LocaHostName 返回本地機器的名字
LocalIP 本地電腦的 IP 位址
LocalPort 資料傳送的埠 (客戶) 或代表一個連接 (伺服器)
Name 對象名
Object 運行時自動創建, 僅在 VFP 中.
Protocol 使用的協定 TCP (0) 或 UDP (1)

屬性 說明
RemoteHost 返回遠端電腦的埠
RemoteHostIP 返回遠端電腦 IP
RemotePort 返回遠端電腦上的連接埠
SocketHandle 返回控制項當前連接的控制碼
State 返回控制項的狀態:
0 = 已關閉
1 = 打開
2 = 等待連接
3 = 正在連接
4 = 決定主機
5 = 主機已決定
6 = 正在連接
7 = 已連接
8 = 連接被遠端電腦關閉
9 = 錯誤

在 VFP 中使用它
在 VFP 中使用 ActiveX Winsock 時你必須牢牢記住:
在運行任何 ActiveX 方法前, 必須添加 .F. 到應用程式的 AutoYeld 屬性 (application.autoyield = .f.);
所有與 Windsock 相關的方法, 事件或屬性必須加上 object 首碼(thisFORM.wsock1.OBJECT.connect)
VFP 不能處理字串中的 CHR(0) 字元. 因此, 如果你要處理帶有這些內容的資料就需要一位元組一位元組地讀緩衝中接收到的資料. 例如, 就象連接到 Unix 伺服器一樣.
讓我們看看示例 1 來開始測試我們的過程:

它由兩個表單組成: 1 個客戶表單和一個伺服器表單. 它的功能是從客戶傳送一個文本資訊到伺服器. 另外伺服器以小寫方式返回相同的資訊.
請注意在兩個表單的 INIT 方法中的命令 Application.AutoYield = .f.. 這意味著我們告訴 VFP 不處理方法中的每一個代碼行, 讓 ActiveX 自己控制它的事件. 在表單的 CLOSE 方法中我們包括了 Application.AutoYield = .t. 來允許 VFP 按一般方法控制事件.
在 SERVER 表單的 INIT 方法中有兩個重要的命令:
thisFORM.sock1.object.LocalPort = 3001
使用以上命令, ActiveX Winsock 在埠 3001上接收連接.
thisFORM.sock1.object.Listen()
該命令告訴 Winsock to 等待連接. 從此時開始, 上面的命令中定義的埠將打開並等待一個連接.
當檢測到連接時, 將觸發 ConnectionRequest 事件, 發送這個新連接的控制碼作為一個參數. 查看示例中的該方法的詳細情況:
This.object.close()
確信沒有其他未決的連接並停止等待.
This.object.Accept(requestid)
運行 Accept 方法, 發送連接控制碼作為參數. 僅現在連接是設置了的.
現在, 讓我們到 CLIENTE 表單, 在發送按鈕的 CLICK 方法上:
lc_local_IP = thisFORM.sock1.object.LocalIP
我們用伺服器的 IP 位址定義一個變數. 在此情況下, 我們從 Winsock 的 LocalIP 屬性來獲得當前電腦的位址.
lc_local_Port = 3001
我們定義了一個將連接到伺服器埠的變數. 請確保該埠對於客戶和伺服器是相同的.
thisFORM.sock1.object.close()
確信沒有未決的連接, 並不再等待另一個連接.
thisFORM.sock1.object.Connect(lc_local_IP,lc_local_Port)
用 IP 位址和埠為參數運行方法來連接伺服器..
在這一點上, 我們可以看到一個迴圈. 它的主要功能是檢查 Winsock 的狀態和等待連接的確認.
定義一個期限是重要的, 否則此處的迴圈將有可能使系統崩潰.
另一個重要的東西是注意迴圈中的 inkey(0.1), 用於避免不必要的使用 CPU 資源.
在連接成功後並確認後, 我們可以看到以下命令:
thisFORM.sock1.object.SendData(trim(thisFORM.texto.value))
運行該方法來傳送資料. 在我們的特寫場合, 是發送文本框 TEXTO 中的內容.
在下一階斷, 我們再次看到一個與前面非常相似的迴圈. 它檢查 ENVIADO_OK 變數的內容. 當資料完成後, Winsock 的 SendComplete 事件將自動運行, 且它將包含一個 .T. 到變數中.
現在我們可以看到另一個等待伺服器 (SERVIDOR) 回應的迴圈.
現在讓我們回到 SERVIDOR 表單, 在 Winsock' 的 DataArrival 事件中. 該事件在每次從遠端電腦上接收到資料時執行. 緩衝的位元組數作為參數給出.
LPARAMETERS bytestotal
lc_buffer = space(bytestotal)
現在我們用 Winsock 的緩衝大小定義一個變數作為緩存.
this.object.GetData(@lc_buffer)
我們運行 GetData 方法, 給它一個要接收緩衝中的資料的變數名引用 (@). 該方法也會清除 Winsock 的緩衝.
thisFORM.retorno.value = lc_buffer
在這一點上, 我們展示已被 GetData 方法填充了的變數的內容.
this.object.SendData(lower(lc_buffer))
作為一個對客戶 (CLIENTE) 的回應我們以小寫方式發送緩衝中的內容.
回到 CLIENTE 表單, 在 Winsock 的 DataArrival 方法中, 我們可以看到它獲得了 Winsock 的緩衝中的內容並將它放入到文本框 RETORNO 中, 處理結束.
繼續捍代碼, 我們用 thisFORM.sock1.object.close() 命令關閉連接, 觸發伺服器 (SERVIDOR) 的 CLOSE 事件:
this.object.Close()
當前連接已經關閉. 無論是在 SERVIDOR 表單還是在 CLIENTE 表單中, 在 CLOSE 事件中的該命令是非常重要的, 否則 Winsock 將耗盡機器的所有資源, 因為它會在有些地方進行迴圈.
this.object.Listen()
現在我們運行方法, 這樣它可以等待下一個連接.
讓我們到使用 Winsock 的示例 2:
創建一個聊天
我們通常希望在我們的程式內部進行聊天. 好吧, 該示例就是關於該功能的. 為了讓它更簡單些, 該資源以只在局域網中運行的方式創建, 因為它使用一個表來保存一些重要的資訊. 因此它不能在 Internet 連接上工作.
該功能以非常簡單的方式運行. 表 USER_ONLINE.DBF 是關鍵. 在該表中有以下欄位:
  欄位 類型 大小 說明
USUARIO 字元 15 保存登錄的用戶名
IP_USER 字元 15 保存電腦的 IP
PORT_USER 數值 5 保存由電腦生成的埠
ON_CHAT 邏輯 定義用戶是否在進行聊天

在運行 CHAT 表單集時, 出現的第一個表單是用戶表單 (USUARIO). 在該表單上, 我們選擇或輸入想與之聊天的用戶. 在得到確認後, 生成的註冊用 RLOCK 鎖住, 因此, 沒有其他終端可以再使用它. 然後, 讓表單不可見並顯示 ON_LINE 表單.
在 ON_LINE 表單的 TIMER1 中計時器 5 秒鐘觸發一次, 運行 USERS 方法. 最後的運行遍曆表試圖鎖定每一個註冊. 在它不能鎖住一個註冊時, 就意味著該用戶線上, 且必須放入列表框 LISTA 中.
準備好了! 在程式的這一點上, 我們可以控制用戶訪問並知道誰線上誰不線上.
雙擊列表框中的用戶名, 程式將試圖打開一個聊天, 在檢查了用戶真的線上後 (試著鎖註冊) 或檢查 ON_CHAT = .T. 變數看其是否正在與另一個用戶聊天. 在聊天被設置後, 他會得到一個 IP 號並從表中選擇用戶埠並試著連接. 這就是 Winsock 什麼時候參與進來的.
一但連接成功, 將打開一個新的表單: CHAT 表單. ON_CHAT 變數被設置為 .T. 因此在終端可以與另一個有關的終端進行聊天.
在這一點上, 我們的連接已經成功且 CHAT 視窗已經打開. 現在可以進行通信了.
在打開的 CHAT 表單上, 我們用 CommandButton 命令按鈕來發送寫到編輯框 MSG 中的文本. 該過程使用了 Send 方法.
要關閉當前的對話, 要做的所有事情就是關閉 CHAT 視窗. 另一個機器上的視窗也會自動關閉. 在這一點上, ON_CHAT 變數已經包含了 .F. 值, 並且可以接收新的聊天請求.
分析該示例中使用的各個方法是重要的, 因為所有便於理解 Winsock 動作的解釋都在代碼中.
Internet
所有 Internet 通信遵循一些預定的標準 (RFC) 如 HTTP, FTP, POP, SMTP, IRC, 等.
在已有的定義中, 默認情況下, 每一個服務將有一個命令組, 各命令組在接收到該命令後將有一個 reply-code 發送自伺服器. 這回復通信命令是否成功地接收了. 因此, 要使用任何採用 RFC 約定的應用程式, 我們必須預先知道它的命令和回復.
我建議你訪問 www.networksorcery.com/enp/default0401.htm 網站來熟悉所有標準. 你也可以用其他搜索引擎來搜索 RFC 標準.
FTP 與 Winsock
 
在示例 3 中我們將看看它是如何連接到 FTP, 列出 FTP 上的檔案名和從 FTP 下載檔的.
FTP 協定使用兩個 Winsocks: 其中一個用於管理發送命令到伺服器; 另一個接收資料 (檔, 目錄等) 傳送. 第二個 Winsock 是一個被動連接, 意思是伺服器要連接到它. 對於每一個資料傳送它需要通知伺服器將要連接的 IP 和埠. 這些資料將由我們的 Gera_Porta() 方法生成.
在命令按鈕 Conectar 中我們設置連接. 重要地注意是在 Winsock 的 .Connect 方法被調用後我們必須運行 Wait("220") 方法. 該方法的主要目的是等待伺服器的回復, 其中的 220 意思是連接成功.
然後, 我們運行方法
.Enviar ("User " + alltrim(thisFORM.user.value),"331")
該方法發送用戶到伺服器, 並等待來自伺服器的 331 回應.
在用戶名和口令被接收後, 運行方法 lista_dir("*.zip"). 該方法詢問 FTP 伺服器上的所有 *.zip 文件. 可能它找不到任何 zip 檔, 程式將詢問 *.exe.
現在我們有了一個伺服器的檔清單, 我們將獲取最後的檔並用 .Download(). 方法下載它. 在所有資料都接收完後, 伺服器將發送一個 226 回應, 通知進程結束. 但是, 緩衝仍然保持可用, 因此我們必須等待到下載的結束.
在下載完成後, 程式詢問要發送到伺服器的檔. 在 .upload() 方法中我們可以觀察到代碼. 這些代碼用 32 Kbytes 緩衝發送檔.
認真查看上面示例中的每一個方法中的代碼是重要的, 因為所有的說明都在其中.
用 Winsock 發送的接收 e-mail
在寫程式時, 許多開發者需要從程式發送或接收 e-mail. 最流行的方案是通過 Outlook Express. 但有可能電腦中沒有該 e-mail 工具. 咋個辦?
在示例 4 中我們將分析一個簡單的允許從程式內發送 e-mail 的方法.
從 Conectar 命令按鈕中, 運行方法 .Conecta_Pop(). 該方法連接到 POP 伺服器交等待一個伺服器的 +OK 回應. 伺服器處理身份鑒定, 發送用戶名和口令, 並回到命令按鈕.
現在調用 .checa_msg() 方法. 它發送 STAT 命令到伺服器, 並等待伺服器的 +OK 資訊. 稍過片刻, 收件箱中的 e-mail 被發送.
使用命令 RETR n, 其中 n 是希望的資訊號, 我們必須處理下載各個資訊(譯者注: 一個資訊就是一個郵件).
你可以向該方法傳遞一個 .t. 參數, 它將刪除用 DELE n 命令刪除資訊 (再次重申 n 是要處理的資訊號).
再次回到命令按鈕, 我們可以看到 .Conecta_Smtp(). 方法被調用. 該方法連接到 SMTP 伺服器並等待回應. 接著, 它用 HELO nome_da_esta玢o 命令來處理 SMTP 伺服器上的身份識別.
現在我們調用 .envia_msg() 方法. 在該方法中, 顯示 e-mail 頭並且我們必須發送 RSET 命令來開始發送 e-mail 到伺服器. 各收件人用 RCPT TO: endere鏾_email 命令發送. 伺服器將不檢查該位址.
在所有位址都發送後, 為了準備伺服器接收 e-mail, 另一個命令 DATA 將被發送. 該過程以 8K 的包發送.
最後, 我們發送命令 CHR(13)+CHR(10) +"." + CHR(13)+CHR(10) 到伺服器, 通知資訊發送完畢.
看看要發送和接收一個 e-mail 有多容易吧?
一些 SMTP 伺服器要求身份鑒定. 身份鑒定可以用兩種方法進行:
作為一個用戶用他的口令連接到 POP 伺服器, 然後立即斷開. (我們在檢查新的郵件時已經這樣做了).
用 UUCODE Base 64 加密口令識別你自己到 SMTP 伺服器. 我們將不討論這個細節, 因為我們必須寫一個演算法這樣我們的示例將太複雜. 但是, 對於使用 Visual FoxPro 7 的開發者, 這只需用一個 VFP 自身的函數: STRCONV (dados,13) 或 STRCONV (dados,14).
我們建議你查看上面示例中的每一個方法, 因為所有解釋都在其中.
結論
從以上的示例中, 我們可以注意到在 VFP 中使用 Winsock 是非常簡單的任務. 我們所需要做的只是知道命令集和回應, 我們可以處理 Internet 標準 (RFC) 或象在聊天示例中一樣開發一個唯一的標準.
我們也可以觀察所有示例中的常用方法. 這意味著可以開發一個符合需要標準的單一的單化我們的更多的工作的類.

_________________
#############################
快樂媽咪系列幸福宅配,喝十全雞湯~原來幸福那麼簡單!!

學會VFP使用者社區的搜尋,Code才會更有趣~
#############################
回頂端
檢視會員個人資料 發送私人訊息
Ruey



註冊時間: 2003-03-12
文章: 1698
來自: tunglo

第 2 樓

發表發表於: 星期六 五月 24, 2003 4:53 pm    文章主題: 引言回覆

WinSocket相關文章
*!*
*!* Save As Url2File.prg // Do it
*!*
Declare INTEGER URLDownloadToFile IN "urlmon" ;
INTEGER ,String,String,INTEGER ,INTEGER

strLocalPath='C:\temp\'
strUrl='http://123.123.123.1/sample.jpg'
strUrl='http://communities.msn.com/_Secure/' ;
+'0KAAAAHENVAStPPrZwWyaBLvSOzmr7XU8oWO!OSfWPIDAXSs' ;
+'*TznVOfhs4HdIKH7KlGOyFtAHYwc/TRUCK.jpg'
strLocalFullName = FORCEPATH( justFName( strUrl ) , strLocalPath )

if URLDownloadToFile(0, strURL,strLocalFullName, 0, 0) = 0
? '_OK_'
_Screen.WindowState = 2
_Screen.AddObject( 'oImage' ,'Image' )
with _Screen.oImage
.Top = 0
.Left = 0
.Width = 600
.Height = 400
.Picture = strLocalFullName
.Visible = .t.
endwith
else
? '_Error_'
endif

return
*
*上面的程式--以滑鼠MARK 之後-滑鼠右鍵 複製------
*
*然後,貼到 MS-Word 中 ------
*然後,再以如上 相同的方法 從 MS-WORD中複製出來......||可得
*********************From Jack許
*********************


Jack許

_________________
#############################
快樂媽咪系列幸福宅配,喝十全雞湯~原來幸福那麼簡單!!

學會VFP使用者社區的搜尋,Code才會更有趣~
#############################
回頂端
檢視會員個人資料 發送私人訊息
Ruey



註冊時間: 2003-03-12
文章: 1698
來自: tunglo

第 3 樓

發表發表於: 星期六 五月 24, 2003 4:53 pm    文章主題: 引言回覆

WinSocket相關文章
x = Create("InetCtls.Inet")
x.proxy = "192.168.6.3"
x.RemotePort = "8080"
x.RequestTimeOut = 1000

z = x.OpenURL("http://www.yourdon.com/photos/Taos/PIC00009-tb.JPG", 1)
f=FCreate("file.jpg")
for i = 1 to ALen(z)
FWrite(f, chr(z[i]))
endfor
FClose(f)


原作者Chris Lee

_________________
#############################
快樂媽咪系列幸福宅配,喝十全雞湯~原來幸福那麼簡單!!

學會VFP使用者社區的搜尋,Code才會更有趣~
#############################
回頂端
檢視會員個人資料 發送私人訊息
Ruey



註冊時間: 2003-03-12
文章: 1698
來自: tunglo

第 4 樓

發表發表於: 星期五 九月 22, 2006 8:34 am    文章主題: 引言回覆

補 /如何在 VisualFoxPro 使用 Winsock ActiveX 控件

http://support.microsoft.com/kb/315124/zh-cn

_________________
#############################
快樂媽咪系列幸福宅配,喝十全雞湯~原來幸福那麼簡單!!

學會VFP使用者社區的搜尋,Code才會更有趣~
#############################
回頂端
檢視會員個人資料 發送私人訊息
Taikey



註冊時間: 2004-09-20
文章: 5


第 5 樓

發表發表於: 星期二 四月 02, 2013 6:51 pm    文章主題: 引言回覆

windows xp 找不到 WINSOCK.OCX
回頂端
檢視會員個人資料 發送私人訊息
ezpos



註冊時間: 2011-04-20
文章: 323


第 6 樓

發表發表於: 星期四 一月 23, 2014 9:34 am    文章主題: 引言回覆

如果不想使用.winsock.ocx...可以使用底下的..只需要另外一個檔案就可以發布


測試過可以使用....
http://www.exapps.co.za/content/visual-foxpro-9-winsock-class-0


LOCAL loWinSock
loWinSock = null

SET PROCEDURE TO WinSock ADDITIVE
loWinSock = CREATEOBJECT("WindowsSocket")
loWinSock.SetCode("SomeCode")

ACTIVATE SCREEN
CLEAR

?"Connecting to 127.0.0.1 on port 25"
IF loWinSock.ConnectToTCPIPv4Address("127.0.0.1", 25)
?"Connected to 127.0.0.1 on port 25"
?loWinSock.Receive()
?"Sending HELO BOB" + CHR(13) + CHR(10)
?loWinSock.Send("HELO BOB" + CHR(13) + CHR(10))
?loWinSock.Receive()
ELSE
?"Connection to 127.0.0.1 on port 25 failed"
ENDIF

?"Disconnecting from 127.0.0.1 on port 25"
loWinSock.Disconnect()
loWinSock = null
SET PROCEDURE TO
?"Complete"

_________________
ezPos收銀機 簡單好用低成本 http://www.ezpos.info
全新美觀的POS收銀機.POS軟硬體耗材.
軟體客制化.網站規劃....能賺錢的都可以找我

http://www.twelife.com 台灣生活網
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
從之前的文章開始顯示:   
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區 所有的時間均為 台北時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
無法 在這個版面附加檔案
無法 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作