250 likes | 410 Views
感測網路實做. Windows winsock 實驗 (using UDP). UDP winsock 實驗. 實驗目標. 本 PPT 為此實習的 part-2 ,旨在介紹 winsock 的編程方式 估計讓學生學習到以下概念 : Window socket 的 UDP 協定傳輸 / 接收程式寫法 簡介 TCP 協定的程式寫法. Winsock 發送端編 程 介紹. Client-Server model ( Client ). Client– 架構. 本次實習採用 client-server 的架構,並使用 UDP 來傳送。
E N D
感測網路實做 Windows winsock 實驗 (using UDP)
UDPwinsock 實驗 實驗目標 • 本PPT為此實習的part-2,旨在介紹winsock的編程方式 • 估計讓學生學習到以下概念: • Window socket 的UDP協定傳輸/接收程式寫法 • 簡介TCP協定的程式寫法
Winsock 發送端編程介紹 Client-Servermodel(Client)
Client–架構 本次實習採用client-server的架構,並使用UDP來傳送。 右圖是Client的程式基本架構 所列出的是重要的function。
程式設計-Enablewinsock 呼叫WSAStartup()來進行windowssocket的初始化。 沒使用的話,winsock相關function都會失敗 範例程式: WORD socket_version = MAKEWORD(2,2); WSADATA wsadata ; if(WSAStartup(socket_version,&wsadata)!=0) { printf("WSAStartip failed !\n"); return 0; }
程式設計-Enablewinsock • WORD socket_version = MAKEWORD(X,Y); 指定準備載入windowssocketsDLL的版本,高位元組指定library的副版本(X),低位元組指定主版本(Y) • WSADATA wsadata; 記載了被載入的LIBRARY的有關資訊(支援版本、最大的sockets數..等) • if(WSAStartup(socket_version,&wsadata)!=0) 啟動winsocket,記得wsadata部分要加&,用call by reference的方式傳進去function之中,WSAStartup啟動成功回傳1,失敗回傳0
程式設計-CreateSockets 呼叫socket()來建立一個socket,然後再判斷是否建立成功,失敗的話使用WSACleanup將winsock關閉並發警告。 範例程式: SOCKETsocket_code =socket(AF_INET,SOCK_DGRAM,0); if(socket_code == INVALID_SOCKET) { printf("socket() failed \n"); WSACleanup(); return 0; } else { printf("socket() success\n"); }
程式設計-CreateSockets • socket( intaf , inttype , intprotocol); Socket() function會回傳建立好的socket的索引號 af:協定的位址家族 AF_INET(IPv4協定)、 AF_INET6(IPv6協定) type:協定的Socket類型 SOCK_STREAM(TCP類) SOCK_DGRAM(UDP類) SOCK_RAW(原始) protocol:該欄位用來限定接收的封包類型,使用UDP或TCP時,填0就好 • WSACleanup(); 將winsock卸載掉,通常用再發生錯誤,或是正常關閉winsock時使用。
程式設計-UseSockets 此段為呼叫sendto()來發送資料,發送10次之後結束發送 範例程式: #define BUFFER_SIZE 1024 #define UDP_PORT1234 char buffer[BUFFER_SIZE]={"winsock UDP send/receive lab"}; SOCKADDR_IN socket_mode ; socket_mode.sin_family =AF_INET; socket_mode.sin_port =htons((short)UDP_PORT); socket_mode.sin_addr.s_addr = inet_addr("127.0.0.1"); If ( sendto( socket_code , buffer , BUFFER_SIZE , 0 , (SOCKADDR*)&socket_mode , sizeof(socket_mode) )==SOCKET_ERROR ) { printf("sendto() failed \n"); }
程式設計-UseSockets • #define BUFFER_SIZE 1024 Winsock中傳輸資料採取bytebuffer的形式,所以需要先定義要以多大的buffer來傳資料,此範例中以1024 byte為一個buffer的單位 • #define UDP_PORT5000 指定要使用的port • SOCKADDR_IN socket_mode; Socket address information,此結構中定義了: • sin_family:位址家族,跟socket()中的af定義一樣 • sin_port :要使用的port • sin_addr :要傳輸的位址 • sin_zero:對齊用,data alignment 此結構當作發送時,其port為要送到對方的第幾port 此結構當作接收時,其port當作本地的接收port
程式設計-UseSockets • intsendto ( SOCKET s, constchar FAR *buf, intlen, intflags, conststructsockaddr *to, inttolen) S:傳入要控制的SOCKET結構索引號(由socket()創出來的) Buf:要傳送的buffer len:buffer的大小 flags:影響function的行為,可使用的參數: • 0:無特殊行為 • MSG_DONTROUTE:要求不要routing • MSG_OOB to:資料的位址資訊,可將SOCKADDR_IN的資料轉型為SOCKADDR傳入 tolen:to的size,用sizeof(SOCKADDR_IN)即可
程式設計-CloseSockets 使用完socket之後,如果此socket沒有要在使用,那就呼叫closesocket來把這個socket摧毀。 如果沒有要在使用winsock,那就呼叫WSACleanup,來disable winsock 範例程式: closesocket(socket_code); WSACleanup();
Winsock 接收端編程介紹 Client-Servermodel(Server)
Server–架構 本次實習採用client-server的架構,並使用UDP來傳送。 右圖是Server的程式基本架構 所列出的是重要的function。
程式設計-Enablewinsock 呼叫WSAStartup()來進行windowssocket的初始化。 沒使用的話,winsock相關function都會失敗
程式設計-Enablewinsock • WORD socket_version = MAKEWORD(X,Y); 指定準備載入windowssocketsDLL的版本,高位元組指定library的副版本(X),低位元組指定主版本(Y) • WSADATA wsadata; 記載了被載入的LIBRARY的有關資訊(支援版本、最大的sockets數..等) • if(WSAStartup(socket_version,&wsadata)!=0) 啟動winsocket,記得wsadata部分要加&,用call by reference的方式傳進去function之中,WSAStartup啟動成功回傳1,失敗回傳0
程式設計-CreateSockets 呼叫socket()來建立一個socket,然後再判斷是否建立成功,失敗的話使用WSACleanup將winsock關閉並發警告。
程式設計-CreateSockets • socket( intaf , inttype , intprotocol); Socket() function會回傳建立好的socket的索引號 af:協定的位址家族 AF_INET(IPv4協定)、 AF_INET6(IPv6協定) type:協定的Socket類型 SOCK_STREAM(TCP類) SOCK_DGRAM(UDP類) SOCK_RAW(原始) protocol:該欄位用來限定接收的封包類型,使用UDP或TCP時,填0就好 • WSACleanup(); 將winsock卸載掉,通常用再發生錯誤,或是正常關閉winsock時使用。
程式設計-BindPort • 在創造socket完成之後,與發送端不同的是,我們需要指定一個port給socket做為接收用途,將一個port綁定給某個socket使用,這個動作就叫做bind。 • Bind之後,socket就可以接收送到這個port的封包資料。
程式設計-BindPort • SOCKADDR_IN socket_mode; Socket address information,與接收端的結構一樣,但是意思不大一樣:: • sin_family:位址家族,跟socket()中的af定義一樣 • sin_port :要使用的port • sin_addr :表示本機網卡IP, 即假設本機上有2張網卡192.168.0.1、 192.168.0.2,如果參數使用INADDR_ANY,則送到這2 張網卡上的資料都可以接到,如果參數使用其中一張網 卡的IP,則代表只讀這張網卡送來的資料。 • Int bind (SOCKET s , conststructsockaddr *addr, intnamelen); 用來綁定port給某個socket使用,成功回傳為0,失敗則為SOCKET_ERROR s:傳入要控制的SOCKET結構索引號(由socket()創出來的) addr:資料的位址資訊,即設定port、ip等的data,可將SOCKADDR_IN的 資料轉型為SOCKADDR傳入 namelen:addr的size,用sizeof(SOCKADDR_IN)或sizeof(傳入addr的變數) 即可
程式設計-UseSockets • 當socket都設定好之後,我們使用一個while迴圈,搭配recv() function來接收資料,然後把它顯示出來 • 裡需要特別注意,我們的socket沒有做過特別設定,所以屬於阻塞模式,recv()會hold住,直到有資料進來才會執行接下來的指令
程式設計-UseSockets • #define BUFFER_SIZE 1024 Winsock中傳輸資料採取bytebuffer的形式,所以需要先定義要以多大的buffer來傳資料,此範例中以1024 byte為一個buffer的單位 • #define UDP_PORT5000 指定要使用的port
程式設計-UseSockets • intsendto ( SOCKET s, constchar FAR *buf, intlen, intflags, conststructsockaddr *to, inttolen) S:傳入要控制的SOCKET結構索引號(由socket()創出來的) Buf:要傳送的buffer len:buffer的大小 flags:影響function的行為,可使用的參數: • 0:無特殊行為 • MSG_DONTROUTE:要求不要routing • MSG_OOB to:資料的位址資訊,可將SOCKADDR_IN的資料轉型為SOCKADDR傳入 tolen:to的size,用sizeof(SOCKADDR_IN)即可
程式設計-CloseSockets 使用完socket之後,如果此socket沒有要在使用,那就呼叫closesocket來把這個socket摧毀。 如果沒有要在使用winsock,那就呼叫WSACleanup,來disable winsock
實驗要求 寫一支程式,連續發送10個封包出去,發送內容不拘,但請在程式中print出你發送什麼。 採用UDP結構,使用port5000,IP用127.0.0.1即可 並完成接收端程式,讓接收端程式能夠收到發送的封包 初步結果: Send receive