//Logo Image
作者:蔡宗成(2005-01-26);推薦:吳昌暉、徐業良(2005-01-26);最近更新:徐業良(2005-02-27)

PIC_SERVER教材(9)—以VB設計TCP/UDP之網路傳輸應用

本文首先介紹使用Visual Basic所提供的Microsoft Winsock Control控制元件(MSWINSCK.OCX),設計UDPTCP兩種通訊協定的ClientServer應用程式,達成訊息傳遞功能。了解Visual BasicUDP/TCP的基本功能後,就可自行開發PIC_SERVERUDP/TCP應用程式。

1.     Microsoft Winsock Control控制元件簡介

Microsoft Winsock Control控制元件支援UDP(User Datagram Protocol)TCP(Transmission Control Protocol)兩種通訊協定。UDP是非連結式通訊協定,不須建立特定的網路連結,只要設定電腦間的IP位址與使用相同的Port,即可互相傳遞訊息。TCP是連結式通訊協定,用戶端電腦與伺服端電腦必須先建立網路連結,便可在此連結下,互相傳遞資料與訊息。

使用UDP通訊協定發送訊息相當於寄普通信件,郵局不會告知寄件人是否將信件送達至收件人;使用TCP通訊協定則相當於寄雙掛號信件,郵局會告知寄件人是否已將信件送達收件人(若未完成則會有逾時timeout信號)。UDP可說是發了就不管,TCP則會在時限之內,若沒有回音就不斷嘗試重發,因此在網路吵雜的環境裡,TCP成功完成傳信任務的機率較高,但效率也較低且耗時,且成功完成傳信任務並不保證信中的內容無誤。

Visual Basic提供一項Microsoft Winsock Control控制元件(MSWINSCK.OCX),作為程式設計者開發應用程式與UDPTCP通訊協定之間的橋樑,不須深入了解網路傳輸的理論,只要設定此控制元件所提供的屬性(Properties),應用其事件(Events)及方法(Methods),即可開發Client(用戶端:主動先開口尋求連結)與Server(伺服端:被動答話接受連結)應用程式。

由於Microsoft Winsock Control控制元件並不是VB預設的控制元件,所以必須自行引用至程式專案中。如圖1,在VB程式專案中,選擇專案è設定使用元件è選擇Microsoft Winsock Control 6.0,雙擊Microsoft Winsock Control 6.0控制元件後,便會出現在程式專案裡。

1(a). 設定使用元件

1(b). 選擇Microsoft Winsock Control 6.0

1(c). 引用至程式裡

Client/Server架構中“請求-回應”過程之執行流程如圖2,敘述如下:

(1)   如圖2(a)Server端必須先建立可以提供Client端連結的功能,成為Listen狀態,等待Client端連接,而Client端則在“Connect”狀態,嘗試與Server端建立連結。

(2)   Server端接收到來自Client端的「連結請求(Connection Request)」,Server端裡的Microsoft Winsock Control控制元件產生“ConnectionRequest”事件,在此事件中,利用“Accept”方法接收來自Client端的請求,如圖2(b)

(3)   如圖2(c)Client端與Server端建立連結後,Client端開始對Server端傳送資料(SendData)Server端的Microsoft Winsock Control控制元件同時產生“DataArrival”事件,在此事件中,利用“GetData”方法接收Client端所傳送來之資料。

(4)   如圖2(d)Server端也可以傳送資料給Client端,稱為「回應(Response)」,程序同步驟(3)

2(a). 嘗試建立連結

2(b). 建立連結

2(c). Client端傳送資料至Server

2(d). 回應資料

2.     VB建立UDP對話視窗範例程式

UDP是非連結式的通訊協定,主要目的在高速傳遞資料。UDP不須先建立通訊連結,只要設定電腦間的IP位置與使用相同的Port,節省建立連結時間(所以才能高速傳遞資料),但UDP不提供資料錯誤的偵測及資料重送等機制,無法確保資料能完整送達。

本節介紹以VB建立UDP對話視窗之範例程式。Client端範例程式收錄在資料夾C:\YZ_PIC\Samples\pic_SERVER\VB\TCP_UDP\UDP_Client\UDP_Client.vbpServer端為C:\YZ_PIC\Samples\pic_SERVER\VB\TCP_UDP\UDP_Client\UDP_Server.vbp

2.1 Client端範例程式

Client端範例程式外觀如圖3,設計Host_IPPortMsg欄提供使用者輸入數值,一空白視窗將Server端傳回的訊息顯示出來,Send按鈕作為連接和傳輸。表1Client端範例程式所引用的基本控制元件與其屬性值,注意對應前述4個欄位的4TextBox設定值分別為“remote_UDP_server_IP”“remote_port”“Msg”、和“Server_reply”Command_button的設定為“Send_button”。此外Winsock命名為WskClient,採用之Protocal1-sckUDPProtocol

3. Client端範例程式外觀

1. UDP_Client表單之元件與屬性

元件

屬性

設定值

Form

Name

frmClient

Caption

UDP_Client

Frame

Name

Frame1

Label

Name

Label1

Caption

Host_IP

Label

Name

Label2

Caption

Port

Label

Name

Label3

Caption

Msg

TextBox

Name

Msg

Text

Hi, there.

TextBox

Name

remote_port

Text

1055

TextBox

Name

remote_UDP_server_IP

Text

140.138.139.41

TextBox

Name

Server_reply

Text

 

CommandButton

Name

Send_button

Caption

Send

Winsock

Name

WskClient

Protocol

1-sckUDPProtocol

4Client端範例程式程式碼。當使用者按下Send_button按鈕後(Send_button_Click()),設定WskClient.RemoteHostWinsock Client端欲連結遠端的主機名稱或IP位址)為remote_UDP_server_IPremote_UDP_server_IP文字框裡的IP),WskClient.RemotePortWinsock Client端欲連結遠端的主機使用的Port)為remote_portremote_port文字框裡的Port),並使用SendData方法傳送Msg文字框裡的內容。

UDP_Client收到遠方資料傳送過來時,啟動Microsoft Winsock Control控制元件的DataArrival事件(WskClient_DataArrival()),定義strData為一字串變數,使用GetData方法接收資料,並將strData資料顯示在Server_reply文字框裡。

4. UDP_Client之程式碼

2.2 Server端範例程式

Server端範例程式外觀如圖5,設計Local_IP欄顯示Server端的IP位址,Port欄提供使用者設定本Server連接PortMsg欄將Client端傳來的訊息顯示出來,debug_info欄作為顯示速度測試訊息之用,並設計Update按鈕作為更新訊息。表2Server端範例程式所引用的基本控制元件與其屬性值,注意對應前述4個欄位的4TextBox設定值分別為“ServerIP”“ServerPort”“Msg”、和“debug_info”Command_button的設定為“Update_button”。此外Winsock命名為WskServer,採用之Protocal1-sckUDPProtocol

5. Server端範例程式外觀

2. UDP_Server表單之元件與屬性

元件

屬性

設定值

Form

Name

frmServer

Caption

UDP_Server

Frame

Name

Frame1

Label

Name

Label1

Caption

Local_IP

Label

Name

Label2

Caption

Port

Label

Name

Label3

Caption

Msg

TextBox

Name

debug_info

Text

 

TextBox

Name

Msg

Text

 

TextBox

Name

ServerIP

Text

192.11.79.158

TextBox

Name

ServerPort

Text

1055

CommandButton

Name

Update_button

Caption

Update

Winsock

Name

WskServer

Protocol

1-sckUDPProtocol

6UDP_Server之程式碼。在副程式From_Load裡,首先顯示Server端的IP位址,並呼叫Update_button_Click副程式。

在副程式Update_button_Click裡,使用者每按下Update_button一次,先關掉Microsoft Winsock Control控制元件,並使用Bind方法設定Server端的連接Port,接著清空Msg文字框與debug_info文字框裡的內容,msg_count變數歸零。

當收到Client端送來資料時,啟動Microsoft Winsock Control控制元件的DataArrival事件(WskServer_DataArrival()),定義strData為一字串變數,使用GetData方法接收資料,並將資料顯示在Msg文字框中,同時將收到時間、訊息長度、收到訊息次數顯示在debug_info文字框中。接著再將收到通知、收到時間、Client端位址、Port等相關資訊,利用SendData方法自動回傳資料至Client端。

6. UDP_Server之程式碼

2.3 UDP程式測試

啟動資料夾C:\YZ_PIC\Samples\pic_SERVER\VB\TCP_UDP裡的UDP_Client.exeUDP_Server.exe範例程式執行檔,在同一部電腦(IP:140.138.*.*)中進行測試,圖7(a)為執行結果。如圖7(b),在UDP_Client,欲連結端Host_IP必須設定為(140.138.*.*)Port設定為1055Msg文字框裡寫入Hi, there.,按下Send按鈕,便將資料傳送至指定IPPortServer端。

UDP_Server執行時,會讀取Server端的IP位址,顯示在Local_IP文字框,Port設定為1055UDP_Server接收到UDP_Client傳來的資料,並將資料顯示在Msg文字框內,再自動回傳資料給UDP_Client,在UDP_Server,按下Updata按鈕可清空Msg文字框與debug_info文字框內容。UDP_Server每接收到一次資料時,msg_count便會累計加1

7(a). 啟動UDP_Client.exeUDP_Server.exe範例程式執行檔

7(b). UDP_ClientUDP_Server傳送與接收過程

3.     VB建立TCP對話視窗範例程式

TCP是連結式通訊協定,主要目的在提供大量資料的傳遞並確保其傳遞資料無誤,有提供錯誤偵測、資料復原及資料重送等機制。TCP在傳送資料前,會在Server端與Client端間建立通訊連結,再互相傳送資料。

本節介紹以VB建立TCP對話視窗之範例程式。Client端範例程式收錄在資料夾C:\YZ_PIC\Samples\pic_SERVER\VB\TCP_UDP\TCP_Client\TCP_Client.vbpServer端為C:\YZ_PIC\Samples\pic_SERVER\VB\TCP_UDP\TCP_Server\TCP_Server.vbp

3.1 Client端範例程式

Client端範例程式外觀如圖8,同樣設計Host_IPPortMsg欄提供使用者輸入數值,一空白視窗將Server端傳回的訊息顯示出來,Send按鈕作為連接和傳輸,並增加一Status欄位,顯示目前連結狀況。引用元件除Microsoft Winsock Control 6.0控制元件外,還增加了一個Timer作為連線實際時之用。表3Client端範例程式所引用的基本控制元件與其屬性值,注意對應前述4個欄位的4TextBox設定值分別為“remote_IP”“remote_port”“Msg”、和“Message_from_Server”Command_button的設定為“Send_button”。此外Winsock命名為WskClient,採用之Protocal0-sckTCPProtocolTimer則命名為Timer1

8. Client端範例程式外觀

3. TCP_Client表單之元件與屬性

元件

屬性

設定值

Form

Name

frmClient

Caption

TCP_Client

Frame

Name

Frame1

Label

Name

ClientStatus

Caption

Not Connected

Label

Name

Label1

Caption

Host_IP

Label

Name

Label2

Caption

Port

Label

Name

Label3

Caption

Status :

Label

Name

Label4

Caption

Msg

Label

Name

Label5

Caption

 

TextBox

Name

Message_from_Server

Text

 

TextBox

Name

Msg

Text

Anybody home ?

TextBox

Name

remote_IP

Text

140.138.139.41

TextBox

Name

remote_Port

Text

83

CommandButton

Name

Send_button

Caption

Send

Timer

Name

Timer1

Enable

False

Winsock

Name

WskClient

Protocol

0-sckTCPProtocol

9TCP_Client之程式碼。當按下Send_button時,啟動Timer1,並設定Timer1的時間週期為3000ms,清空Message_from_Server文字框,WskClientState值為6時,代表正在嘗試與Server端連線中,如果不等於6,設定欲連結Server端的IP位址與Port,並執行WskClient_Connect副程式,代表已連線成功。否則ClientStatus顯示“Connecting…”

WskClient_Connect副程式中,當連線成功時,ClientStatus顯示”Connected.”,並將Msg文字框裡的內容藉由Microsoft Winsock Control控制元件的SendData方法傳送出去。

Client端接收到資料時,啟動DataArrival事件,定義strData為一字串變數,使用GetData方法接收此strData資料,將所接收到的資料顯示在Message_from_Server文字框,接著結束連線,ClientStatus顯示“Disconnected.”,關閉Timer1

Timer1_Timer副程式裡,當Timer1啟動後經過3000ms還無法與Server端建立連線,便結束連線,ClientStatus顯示“Not Connected.”,並出現訊息提示框(MsgBox)告知“Failed to send message in 3 sec.”

9. TCP_Client之程式碼

3.2 Server端範例程式

Client端範例程式外觀如圖10,同樣設計Local_IP欄顯示Server端的IP位址,Port欄提供使用者設定本Server連接PortMsg欄將Client端傳來的訊息顯示出來,debug_info欄作為顯示速度測試訊息之用,Update按鈕作為更新訊息,並增加一Status欄位,顯示目前連結狀況。引用元件除Microsoft Winsock Control 6.0控制元件外,還增加了一個Timer作為連線實際時之用。表4Server端範例程式所引用的基本控制元件與其屬性值,注意對應前述4個欄位的4TextBox設定值分別為“ServerIP”“ServerPort”“Msg”、和“debug_info”Command_button的設定為“Update_button”。此外Winsock命名為WskServer,採用之Protocal0-sckTCPProtocolTimer則命名為Timer1

10. Server端範例程式外觀

4. TCP_Server表單之元件與屬性

元件

屬性

設定值

Form

Name

frmServer

Caption

TCP_Server

Frame

Name

Frame1

Label

Name

Label1

Caption

Local_IP

Label

Name

Label2

Caption

Port

Label

Name

Label3

Caption

Status :

Label

Name

Label4

Caption

Msg

Label

Name

ServerStatus

Caption

Server is Idle

TextBox

Name

debug_info

Text

 

TextBox

Name

Msg

Text

 

TextBox

Name

ServerIP

Text

192.11.79.158

TextBox

Name

ServerPort

Text

83

CommandButton

Name

Update_button

Caption

Update

Timer

Name

Timer1

Enable

True

Winsock

Name

WskServer

Protocol

0-sckTCPProtocol

11TCP_Client之程式碼。首先顯示Server端的IP位址,並呼叫WskServer_Listen()副程式。

WskServer_Listen()副程式裡,關閉Timer1,使用Close方法關閉連線,設定WinsockLocalPort屬性為ServerPort文字框裡的IP位址,再使用Listen方法等待Client端之連線請求,ServerStatus顯示“Listening ...”

Client提出連線需求時,引發WinsockConnectionRequest事件,開始判斷WinsockState為何。如果StatesckConnected,表示Server已被其他Client連結,出現提示框,內容為“Server already connected!”,如果不是,先使用Close方法關閉連線,再使用Accept方法取得Client端的IDServerStatus顯示“connected”,啟動Timer1,設定Timer1的週期為10000ms,清空debug_info文字框。

Timer1開始計時10000ms後,呼叫WskServer_Listen()副程式,回復到等待連線(listen)狀態。

Client傳送資料過來時,引發WinsockDataArrival事件,定義strData為一字串變數,使用GetData接收此strData資料,並將資料顯示在Msg文字框裡,,同時將收到時間、訊息長度、收到訊息次數顯示在debug_info文字框中。接著再將收到通知、收到時間、Client端位址、Port等相關資訊使用SendData方法回傳至Client端。

當使用者按下Update按鈕時,清空Msg文字框內容,清空debug_info文字框內容,呼叫WskServer_Listen()副程式,回復到等待連線(listen)狀態。

11. TCP_Server程式碼

3.3 TCP程式測試

啟動資料夾C:\YZ_PIC\Samples\pic_SERVER\VB\TCP_UDP裡的TCP_Client.exeTCP_Server.exe範例程式執行檔,在同一部電腦(IP:140.138.*.*)中進行測試,圖12(a)為執行結果,TCP_Client端的Status顯示“Not Connected”TCP_Server端的Status顯示“Listening…”。如圖12(b),當Client端設定Server端的IP位址與Port,按下Send按鈕,將Msg文字框裡的內容傳送到Server端。

TCP_Server執行時,會讀取Server端的IP位址,顯示在Local_IP文字框,Port設定為83TCP_Server接收到TCP_Client傳來的資料,並將資料顯示在Msg文字框內,再自動回傳資料給TCP_Client,在TCP_Server,按下Updata按鈕可清空Msg文字框與debug_info文字框內容。TCP_Server每接收到一次資料時,msg_count便會累計加1。圖12(c)TCP_Client端所欲連結的IP位址與TCP_Server端不同時,經過3秒後所出現的訊息提示框。

12(a). 啟動TCP_Client.exeTCP_Server.exe範例程式執行檔

12(b). TCP_ClientTCP_Server傳送與接收過程

12(c). 無法連結時出現提示框

4.     使用TCPPIC_SERVER傳遞訊息

client端或Server端以PIC_SERVER取代PC,使用UDPTCP傳遞訊息,需要使用資料夾C:\YZ_PIC\Samples\pic_SERVER\Beginner\中的範例程式ex_4_udp_client.cex_5_udp_server.cex_6_tcp_server.c、及ex_8_tcp_client.c取代前述VB程式。以下敘述以PIC_SERVERServer端、PCclient端,使用TCPPIC_SERVER傳遞訊息的設定方式。

將範例程式C:\YZ_PIC\Samples\pic_SERVER\Beginner\ex_6_tcp_server.c載入PIC_SERVER,在ICP中設定local TCP server port的欄位(例如3423),不可與HTTP port相同(例如80),如圖13所示。

Client端的PC則仍執行前述VB程式TCPclient.exe,將其Host_IPPort設定為pic_SERVERIPlocal TCP server port,就可以傳訊給PIC了。例如在Msg文字框裡輸入字串訊息“I am superman”,按下Send按鈕傳遞,PIC_SERVER接收到訊息後再回傳通知給TCP_Client,如圖14

範例程式ex_6_tcp_server.c架構和先前教材中PICC程式十分類似,且範例程式中有很清楚的註解說明,此處不再一一詳加解釋。值得注意的是範例程式ex_6_tcp_server.cTCP通訊部分,主要差異在先前沒有用到的call back函式callback_TCPclientDataArrival()內,即接獲TCP client傳來data後的處理動作,這個callback副程式與VB範例TCP_Server.vbp裡面的副程式

Private Sub WskServer_DataArrival(ByVal bytesTotal As Long)

的功能與角色完全相同,只是命名的概念有些差異罷了。此外,VBWskServer.GetData strData以及WskServer.SendData (reply_msg)等兩個指令實現接收字串與傳送字串的功能,pic_SERVER則使用 BIOS指令nic_getcnic_putc這兩個指令實現接收一個字元(byte)與傳送一個字元的功能,用printf( nic_putc, )的方式實現傳送字串的功能。總之,要做的事情都一樣,不同的程式語言採用不同的指令與函數實現這些功能。其他的call back函式如callback_TCPserverDataArrival()callback_UDPserverDataArrival()callback_UDPclientDataArrival()也都可以在VB範例中找到相對應的副程式,VB有的通訊功能PIC_SERVER也都有,瞭解VBUDP/TCP就更能瞭解PIC_SERVER了。

13. PIC_SERVER通訊協定設定

14. TCP_ClientPIC_SERVER傳遞訊息

Port改為80,並在Msg文字框裡,輸入GET/index.htmPIC_SERVER收到此指令後將指定網頁內容回傳給TCP_Client,如圖15

15. TCP_Client傳遞指令索取網頁內容

【實驗】

嘗試以以下6種方式執行本教材中提到範例程式執行檔UDP_Client.exeUDP_Server.exeTCP_Client.exeTCP_Server.exe

(1)    PCPCUDP通訊,只用一台PC,自己發自己收。

(2)    PCPCUDP通訊,用兩台PC,一個發一個收。

(3)    PCPCTCP通訊,只用一台PC,自己發自己收。

(4)    PCPCTCP通訊,用兩台PC,一個發一個收。

(5)    稍微修改VB範例程式,用三台PC互相通訊,第一台PCTCP_client發信給第二台PCTCP_server,第二台PC收到第一台PC送來的信之後,就用UDP把信轉寄給第三台PC。當然,這個實驗用兩台PC也可以玩。

(6)    PCPIC_SERVER,使用UDPTCP兩種模式傳送訊息,並在下週課堂上實際展示。

參考資料

黃嘉輝,2002Visual Basic網際網路程式設計-TCP/IPInternet Programming篇最新版,文魁資訊股份有限公司。