Transcript 範例程式
感測網路實做
Windows winsock 實驗 (using UDP)
1
UDP winsock 實驗
實驗目標
• 本PPT為此實習的part-2,旨在介紹winsock的編程方式
• 估計讓學生學習到以下概念:
• Window socket 的UDP協定傳輸/接收程式寫法
• 簡介TCP協定的程式寫法
2
Winsock 發送端編程介紹
Client-Server model ( Client )
3
Client–架構
本次實習採用client-server的架構,
並使用UDP來傳送。
右圖是Client的程式基本架構
所列出的是重要的function。
4
程式設計-Enable winsock
呼叫WSAStartup()來進行windows socket的初始化。
沒使用的話,winsock相關function都會失敗
範例程式:
WORD socket_version = MAKEWORD(2,2);
WSADATA wsadata ;
if( WSAStartup(socket_version,&wsadata)!=0 )
{
printf("WSAStartip failed !\n");
return 0;
}
5
程式設計-Enable winsock
WORD socket_version = MAKEWORD( X , Y );
指定準備載入windows sockets DLL的版本,高位元組指定library的副
版本(X),低位元組指定主版本(Y)
WSADATA wsadata ;
記載了被載入的LIBRARY的有關資訊(支援版本、最大的sockets數..等)
if( WSAStartup( socket_version , &wsadata ) !=0 )
啟動winsocket,記得wsadata部分要加&,用call by reference的方式
傳進去function之中,WSAStartup啟動成功回傳1,失敗回傳0
6
程式設計-Create Sockets
呼叫socket()來建立一個socket,然後再判斷是否建立成功,
失敗的話使用WSACleanup將winsock關閉並發警告。
範例程式:
SOCKET socket_code =socket(AF_INET,SOCK_DGRAM,0);
if(socket_code == INVALID_SOCKET)
{
printf("socket() failed \n");
WSACleanup();
return 0;
}
else
{
printf("socket() success\n");
}
7
程式設計-Create Sockets
socket( int af , int type , int protocol );
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時使用。
8
程式設計-Use Sockets
此段為呼叫sendto()來發送資料,發送10次之後結束發送
範例程式:
#define BUFFER_SIZE 1024
#define UDP_PORT 1234
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");
}
9
程式設計-Use Sockets
#define BUFFER_SIZE 1024
Winsock中傳輸資料採取byte buffer的形式,所以需要先定義要以多大的
buffer來傳資料,此範例中以1024 byte為一個buffer的單位
#define UDP_PORT 5000
指定要使用的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
10
程式設計-Use Sockets
int sendto ( SOCKET s,
const char FAR * buf,
int len,
int flags,
const struct sockaddr *to,
int tolen)
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)即可
11
程式設計-Close Sockets
使用完socket之後,如果此socket沒有要在使用,那就呼叫
closesocket來把這個socket摧毀。
如果沒有要在使用winsock,那就呼叫WSACleanup,來disable
winsock
範例程式:
closesocket(socket_code);
WSACleanup();
12
Winsock 接收端編程介紹
Client-Server model ( Server)
13
Server–架構
本次實習採用client-server的架構,
並使用UDP來傳送。
右圖是Server的程式基本架構
所列出的是重要的function。
14
程式設計-Enable winsock
呼叫WSAStartup()來進行windows socket的初始化。
沒使用的話,winsock相關function都會失敗
15
程式設計-Enable winsock
WORD socket_version = MAKEWORD( X , Y );
指定準備載入windows sockets DLL的版本,高位元組指定library的副
版本(X),低位元組指定主版本(Y)
WSADATA wsadata ;
記載了被載入的LIBRARY的有關資訊(支援版本、最大的sockets數..等)
if( WSAStartup( socket_version , &wsadata ) !=0 )
啟動winsocket,記得wsadata部分要加&,用call by reference的方式
傳進去function之中,WSAStartup啟動成功回傳1,失敗回傳0
16
程式設計-Create Sockets
呼叫socket()來建立一個socket,然後再判斷是否建立成功,
失敗的話使用WSACleanup將winsock關閉並發警告。
17
程式設計-Create Sockets
socket( int af , int type , int protocol );
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時使用。
18
程式設計-Bind Port
在創造socket完成之後,與發送端不同的是,我們需要指定一個
port給socket做為接收用途,將一個port綁定給某個socket使用,
這個動作就叫做bind。
Bind之後,socket就可以接收送到這個port的封包資料。
19
程式設計-Bind Port
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 , const struct sockaddr *addr , int namelen);
用來綁定port給某個socket使用,成功回傳為0,失敗則為SOCKET_ERROR
s:傳入要控制的SOCKET結構索引號(由socket()創出來的)
addr:資料的位址資訊,即設定port、ip等的data,可將SOCKADDR_IN的
資料轉型為SOCKADDR傳入
namelen :addr的size,用sizeof(SOCKADDR_IN)或sizeof(傳入addr的變數)
即可
20
程式設計-Use Sockets
當socket都設定好之後,我們使用一個while迴圈,搭配recv()
function來接收資料,然後把它顯示出來
裡需要特別注意,我們的socket沒有做過特別設定,所以屬於阻塞
模式,recv()會hold住,直到有資料進來才會執行接下來的指令
21
程式設計-Use Sockets
#define BUFFER_SIZE 1024
Winsock中傳輸資料採取byte buffer的形式,所以需要先定義要以多大的
buffer來傳資料,此範例中以1024 byte為一個buffer的單位
#define UDP_PORT 5000
指定要使用的port
22
程式設計-Use Sockets
int sendto ( SOCKET s,
const char FAR * buf,
int len,
int flags,
const struct sockaddr *to,
int tolen)
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)即可
23
程式設計-Close Sockets
使用完socket之後,如果此socket沒有要在使用,那就呼叫
closesocket來把這個socket摧毀。
如果沒有要在使用winsock,那就呼叫WSACleanup,來disable
winsock
24
實驗要求
寫一支程式,連續發送10個封包出去,發送內容不拘,但請在程式
中print出你發送什麼。
採用UDP結構,使用port 5000,IP用127.0.0.1即可
並完成接收端程式,讓接收端程式能夠收到發送的封包
初步結果:
25
receive
Send