




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、數據通信與計算機網絡設計性實驗指導書一、 實驗目的:1、了解和掌握TCP/IP協議基本原理2、了解網絡環境下的程序設計步驟和過程3、掌握Winsock提供函數的功能和用法二、 實驗要求:1、利用Winsock控件,采用TCP或UDP方式實現服務器和客戶之間建立連接、發送/接收數據。2、在課程設計報告中要求給出程序設計的思想、關鍵程序說明以及服務器和客戶程序運行界面的屏幕截圖。三、 設計思想:傳輸層協議有兩種:TCP和UDP,TCP是可靠傳輸,它把信息包捆綁,在必要的時候,排序和重傳這些信息包以獲得可靠的數據傳輸。UDP支持快速的、無連接的、不可靠的信息包傳輸。創建ServerSocket對象,
2、在某端口提供監聽服務等待來自Client端的服務請求接受Client端的請求,用返回的Socket建立連接通過向Socket中讀寫數據來與Client端通信關閉Socket,結束與當前Client的通信,等待其他請求關閉ServerSocket對象,結束監聽服務Server端Client端關閉Socket,結束與Server端的通信通過向新的Socket中讀寫數據來與Server端通信創建Socket對象,向Server的監聽端口請求建立連接數據通信拆分連接附錄:SOCKET編程1、 SOCKET規范概述 Windows Sockets規范以U.C. Berkeley大學BSD UNIX中流行
3、的Socket接口為范例定義了一套Micorosoft Windows下網絡編程接口。它不僅包含了人們所熟悉的Berkeley Socket風格的庫函數;也包含了一組針對Windows的擴展庫函數,以使程序員能充分地利用Windows消息驅動機制進行編程。 Windows Sockets規范本意在于提供給應用程序開發者一套簡單的API,并讓各家網絡軟件供應商共同遵守。此外,在一個特定版本Windows的基礎上,Windows Sockets也定義了一個二進制接口(ABI),以此來保證應用Windows Sockets API的應用程序能夠在任何網絡軟件供應商的符合Windows S
4、ockets協議的實現上工作。因此這份規范定義了應用程序開發者能夠使用,并且網絡軟件供應商能夠實現的一套庫函數調用和相關語義。 遵守這套Windows Sockets規范的網絡軟件,我們稱之為Windows Sockets兼容的,而Windows Sockets兼容實現的提供者,我們稱之為Windows Sockets提供者。一個網絡軟件供應商必須百分之百地實現Windows Sockets規范才能做到現Windows Sockets兼容。 任何能夠與Windows Sockets兼容實現協同工作的應用程序就被認為是具有Windows Sockets接口。我們稱這種應用程序
5、為Windows Sockets應用程序。 Windows Sockets規范定義并記錄了如何使用API與Internet協議族(IPS,通常我們指的是TCP/IP)連接,尤其要指出的是所有的Windows Sockets實現都支持流套接口和數據報套接口. 應用程序調用Windows Sockets的API實現相互之間的通訊。Windows Sockets又利用下層的網絡通訊協議功能和操作系統調用實現實際的通訊工作。 2、WINDOWS環境下SOCKET基本函數(1)WSAStartup函數int WSAStartup(WORD wVersionR
6、equested,LPWSADATA lpWSAData);使用Socket的程序在使用Socket之前必須調用WSAStartup函數。該函數的第一個參數指明程序請求使用的Socket版本,其中高位字節指明副版本、低位字節指明主版本;操作系統利用第二個參數返回請求的Socket的版本信息。當一個應用程序調用WSAStartup函數時,操作系統根據請求的Socket版本來搜索相應的Socket庫,然后綁定找到的Socket庫到該應用程序中。以后應用程序就可以調用所請求的Socket庫中的其它Socket函數了。該函數執行成功后返回0。 例:假如一個程序要使用2.1版本的Socket,那么程序代
7、碼如下wVersionRequested = MAKEWORD( 2, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); (2)WSACleanup函數 int WSACleanup (void); 應用程序在完成對請求的Socket庫的使用后,要調用WSACleanup函數來解除與Socket庫的綁定并且釋放Socket庫所占用的系統資源。 (3)socket函數SOCKET socket( int af, int type, int protocol ); 應用程序調用socket函數來創建一個能夠進行網絡通信的套接字。第一
8、個參數指定應用程序使用的通信協議的協議族,對于TCP/IP協議族,該參數置PF_INET;第二個參數指定要創建的套接字類型,流套接字類型為SOCK_STREAM、數據報套接字類型為SOCK_DGRAM;第三個參數指定應用程序所使用的通信協議。該函數如果調用成功就返回新創建的套接字的描述符,如果失敗就返回INVALID_SOCKET。套接字描述符是一個整數類型的值。每個進程的進程空間里都有一個套接字描述符表,該表中存放著套接字描述符和套接字數據結構的對應關系。該表中有一個字段存放新創建的套接字的描述符,另一個字段存放套接字數據結構的地址,因此根據套接字描述符就可以找到其對應的套接字數據結構。每個
9、進程在自己的進程空間里都有一個套接字描述符表但是套接字數據結構都是在操作系統的內核緩沖里。下面是一個創建流套接字的例子: struct protoent *ppe; ppe=getprotobyname("tcp"); SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto); (4)closesocket函數 int closesocket( SOCKET s ); closesocket函數用來關閉一個描述符為s套接字。由于每個進程中都有一個套接字描述符表,表中的每個套接字描述符都對應了一個位于操作系
10、統緩沖區中的套接字數據結構,因此有可能有幾個套接字描述符指向同一個套接字數據結構。套接字數據結構中專門有一個字段存放該結構的被引用次數,即有多少個套接字描述符指向該結構。當調用closesocket函數時,操作系統先檢查套接字數據結構中的該字段的值,如果為1,就表明只有一個套接字描述符指向它,因此操作系統就先把s在套接字描述符表中對應的那條表項清除,并且釋放s對應的套接字數據結構;如果該字段大于1,那么操作系統僅僅清除s在套接字描述符表中的對應表項,并且把s對應的套接字數據結構的引用次數減1。 closesocket函數如果執行成功就返回0,否則返回SOCKET_ERROR。 (5)send函
11、數 int send( SOCKET s, const char FAR *buf, int len, int flags ); 不論是客戶還是服務器應用程序都用send函數來向TCP連接的另一端發送數據??蛻舫绦蛞话阌胹end函數向服務器發送請求,而服務器則通常用send函數來向客戶程序發送應答。該函數的第一個參數指定發送端套接字描述符;第二個參數指明一個存放應用程序要發送數據的緩沖區;第三個參數指明實際要發送的數據的字節數;第四個參數一般置0。這里只描述同步Socket的send函數的執行流程。當調用該函數時,send先比較待發送數據的長度len和套接字s的發送緩沖區的長度,如果len大于
12、s的發送緩沖區的長度,該函數返回SOCKET_ERROR;如果len小于或者等于s的發送緩沖區的長度,那么send先檢查協議是否正在發送s的發送緩沖中的數據,如果是就等待協議把數據發送完,如果協議還沒有開始發送s的發送緩沖中的數據或者s的發送緩沖中沒有數據,那么send就比較s的發送緩沖區的剩余空間和len,如果len大于剩余空間大小send就一直等待協議把s的發送緩沖中的數據發送完,如果len小于剩余空間大小send就僅僅把buf中的數據copy到剩余空間里(注意并不是send把s的發送緩沖中的數據傳到連接的另一端的,而是協議傳的,send僅僅是把buf中的數據copy到s的發送緩沖區的剩余
13、空間里)。如果send函數copy數據成功,就返回實際copy的字節數,如果send在copy數據時出現錯誤,那么send就返回SOCKET_ERROR;如果send在等待協議傳送數據時網絡斷開的話,那么send函數也返回SOCKET_ERROR。要注意send函數把buf中的數據成功copy到s的發送緩沖的剩余空間里后它就返回了,但是此時這些數據并不一定馬上被傳到連接的另一端。如果協議在后續的傳送過程中出現網絡錯誤的話,那么下一個Socket函數就會返回SOCKET_ERROR。(每一個除send外的Socket函數在執行的最開始總要先等待套接字的發送緩沖中的數據被協議傳送完畢才能繼續,如果
14、在等待時出現網絡錯誤,那么該Socket函數就返回SOCKET_ERROR) 注意:在Unix系統下,如果send在等待協議傳送數據時網絡斷開的話,調用send的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。 (6)recv函數 int recv( SOCKET s, char FAR *buf, int len, int flags ); 不論是客戶還是服務器應用程序都用recv函數從TCP連接的另一端接收數據。該函數的第一個參數指定接收端套接字描述符;第二個參數指明一個緩沖區,該緩沖區用來存放recv函數接收到的數據;第三個參數指明buf的長度;第四個參數一般置0。
15、這里只描述同步Socket的recv函數的執行流程。當應用程序調用recv函數時,recv先等待s的發送緩沖中的數據被協議傳送完畢,如果協議在傳送s的發送緩沖中的數據時出現網絡錯誤,那么recv函數返回SOCKET_ERROR,如果s的發送緩沖中沒有數據或者數據被協議成功發送完畢后,recv先檢查套接字s的接收緩沖區,如果s接收緩沖區中沒有數據或者協議正在接收數據,那么recv就一直等待,只到協議把數據接收完畢。當協議把數據接收完畢,recv函數就把s的接收緩沖中的數據copy到buf中(注意協議接收到的數據可能大于buf的長度,所以在這種情況下要調用幾次recv函數才能把s的接收緩沖中的數據
16、copy完。recv函數僅僅是copy數據,真正的接收數據是協議來完成的),recv函數返回其實際copy的字節數。如果recv在copy時出錯,那么它返回SOCKET_ERROR;如果recv函數在等待協議接收數據時網絡中斷了,那么它返回0。 注意:在Unix系統下,如果recv函數在等待協議接收數據時網絡斷開了,那么調用recv的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。 (7)bind函數 int bind( SOCKET s, const struct sockaddr FAR *name, int namelen ); 當創建了一個Socket以后,套接字
17、數據結構中有一個默認的IP地址和默認的端口號。一個服務程序必須調用bind函數來給其綁定一個IP地址和一個特定的端口號。客戶程序一般不必調用bind函數來為其Socket綁定IP地址和斷口號。該函數的第一個參數指定待綁定的Socket描述符;第二個參數指定一個sockaddr結構,該結構是這樣定義的: struct sockaddr u_short sa_family; char sa_data14; ; sa_family指定地址族,對于TCP/IP協議族的套接字,給其置AF_INET。當對TCP/IP協議族的套接字進行綁定時,我們通常使用另一個地址結構: struct sockaddr_i
18、n short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero8; ; 其中sin_family置AF_INET;sin_port指明端口號;sin_addr結構體中只有一個唯一的字段s_addr,表示IP地址,該字段是一個整數,一般用函數inet_addr()把字符串形式的IP地址轉換成unsigned long型的整數值后再置給s_addr。有的服務器是多宿主機,至少有兩個網卡,那么運行在這樣的服務器上的服務程序在為其Socket綁定IP地址時可以把htonl(INADDR_ANY)置給s_addr,
19、這樣做的好處是不論哪個網段上的客戶程序都能與該服務程序通信;如果只給運行在多宿主機上的服務程序的Socket綁定一個固定的IP地址,那么就只有與該IP地址處于同一個網段上的客戶程序才能與該服務程序通信。我們用0來填充sin_zero數組,目的是讓sockaddr_in結構的大小與sockaddr結構的大小一致。下面是一個bind函數調用的例子: struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port = htons(8888); saddr.sin_addr.s_addr = htonl(INADDR_ANY);
20、 bind(ListenSocket,(struct sockaddr *)&saddr,sizeof(saddr); (8)listen函數 int listen( SOCKET s, int backlog ); 服務程序可以調用listen函數使其流套接字s處于監聽狀態。處于監聽狀態的流套接字s將維護一個客戶連接請求隊列,該隊列最多容納backlog個客戶連接請求。假如該函數執行成功,則返回0;如果執行失敗,則返回SOCKET_ERROR。 (9)accept函數 SOCKET accept( SOCKET s, struct sockaddr FAR *addr, int FA
21、R *addrlen ); 服務程序調用accept函數從處于監聽狀態的流套接字s的客戶連接請求隊列中取出排在最前的一個客戶請求,并且創建一個新的套接字來與客戶套接字創建連接通道,如果連接成功,就返回新創建的套接字的描述符,以后與客戶套接字交換數據的是新創建的套接字;如果失敗就返回INVALID_SOCKET。該函數的第一個參數指定處于監聽狀態的流套接字;操作系統利用第二個參數來返回新創建的套接字的地址結構;操作系統利用第三個參數來返回新創建的套接字的地址結構的長度。下面是一個調用accept的例子:struct sockaddr_in ServerSocketAddr; int addrle
22、n; addrlen=sizeof(ServerSocketAddr); ServerSocket=accept(ListenSocket,(struct sockaddr *)&ServerSocketAddr,&addrlen); (10)connect函數 int connect( SOCKET s, const struct sockaddr FAR *name, int namelen ); 客戶程序調用connect函數來使客戶Socket s與監聽于name所指定的計算機的特定端口上的服務Socket進行連接。如果連接成功,connect返回0;如果失敗則返回SO
23、CKET_ERROR。下面是一個例子: struct sockaddr_in daddr; memset(void *)&daddr,0,sizeof(daddr); daddr.sin_family=AF_INET; daddr.sin_port=htons(8888); daddr.sin_addr.s_addr=inet_addr("133.197.22.4"); connect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr); 3、RAW模式的SOCKET編程Windows Sockets 是
24、一個編程接口,它是在加州大學伯克利分校開發的套接字接口的基礎上定義的。它包括了一組擴展件,以充分利用 Microsoft Windows 消息驅動的特點。規范的1.1版是在 1993 年 1 月發行的, 版在 1996 年 5 月發行。Windows 2000 支持 Winsock 2.2 版。在Winsock2中,支持多個傳輸協議的原始套接字,重疊I/O模型、服務質量控制等。這里介紹Windows Sockets的一些關于原始套接字(Raw Socket)的編程。同Winsock 1相比,最明顯的就是支持了Raw Socket套接字類型,通過原始套接字,我們可以更加自如地控制Windows下
25、的多種協議,而且能夠對網絡底層的傳輸機制進行控制。(1)創建一個原始套接字,并設置IP頭選項。SOCKET sock;sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);或者:s = WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);這里,我們設置了SOCK_RAW標志,表示我們聲明的是一個原始套接字類型。創建原始套接字后,IP頭就會包含在接收的數據中,如果我們設定 IP_HDRINCL 選項,那么,就需要自己來構造IP頭。注意,如果設置IP_HDRINCL 選項,那么必須具有
26、 administrator權限,要不就必須修改注冊表:HKEY_LOCAL_MACHINESystemCurrentControlSetServicesAfdParameter修改鍵:DisableRawSecurity(類型為DWORD),把值修改為 1。如果沒有,就添加。BOOL blnFlag=TRUE;setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&blnFlag, sizeof(blnFlag);對于原始套接字在接收數據報的時候,要注意這么幾點: 如果接收的數據報中協議類型和定義的原始套接字匹配,那么
27、,接收的所有數據就拷貝到套接字中。 如果綁定了本地地址,那么只有接收數據IP頭中對應的遠端地址匹配,接收的數據就拷貝到套接字中。 如果定義的是外部地址,比如使用connect(),那么,只有接收數據IP頭中對應的源地址匹配,接收的數據就拷貝到套接字中。(2)構造IP頭和TCP頭這里,提供IP頭和TCP頭的結構:/ Standard TCP flags#define URG 0x20#define ACK 0x10#define PSH 0x08#define RST 0x04#define SYN 0x02#define FIN 0x01typede
28、f struct _iphdr /定義IP首部unsigned char h_lenver; /4位首部長度+4位IP版本號unsigned char tos; /8位服務類型TOSunsigned short total_len; /16位總長度(字節)unsigned short ident; /16位標識unsigned short frag_and_flags; /3位標志位unsigned char ttl; /8位生存時間 TTLunsigned char proto; /8位協議 (TCP, UDP 或其他)unsigned short checksum; /16位IP首部校驗和
29、unsigned int sourceIP; /32位源IP地址unsigned int destIP; /32位目的IP地址IP_HEADER;typedef struct psd_hdr /定義TCP偽首部unsigned long saddr; /源地址unsigned long daddr; /目的地址char mbz;char ptcl; /協議類型 unsigned short tcpl; /TCP長度PSD_HEADER;typedef struct _tcphdr /定義TCP首部USHORT th_sport; /16位源端口USHORT th_dport; /16位目的端口unsigned int th_seq; /32位序
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 三江學院《湖湘民俗文化》2023-2024學年第二學期期末試卷
- 浙江電力職業技術學院《建筑設計基礎A1》2023-2024學年第一學期期末試卷
- 遼寧師范大學《抽樣調查方法》2023-2024學年第一學期期末試卷
- 云南工貿職業技術學院《食品安全生產》2023-2024學年第二學期期末試卷
- 山西晉中理工學院《中醫學基礎1》2023-2024學年第一學期期末試卷
- 塔城職業技術學院《無機非金屬材料專業英語》2023-2024學年第二學期期末試卷
- 上海農林職業技術學院《大數據及其應用B》2023-2024學年第二學期期末試卷
- 湖南城建職業技術學院《室內專題設計3》2023-2024學年第一學期期末試卷
- 暨南大學《風景園林管理》2023-2024學年第二學期期末試卷
- 武漢職業技術學院《離散數學及其應用》2023-2024學年第一學期期末試卷
- 2025年北師大版數學六年級下冊教學計劃(含進度表)
- 2025社保政策培訓
- 2025年蘇州工業園區國企招聘筆試參考題庫含答案解析
- 2025年上海市規劃和國土資源管理局所屬事業單位工作人員招考高頻重點提升(共500題)附帶答案詳解
- 超聲檢查的臨床義及超聲報告的解讀課件
- 《空心膠囊規格尺寸及外觀質量》(T-CNPPA 3008-2020)
- 彼得 卒姆托簡介 彼得 卒姆托的建筑解讀 彼得 卒姆托的建筑思想解讀 小32課件講解
- 腦機接口課件
- 【MOOC】供應鏈管理-武漢理工大學 中國大學慕課MOOC答案
- 山東省五級師承結業論文骨傷科一萬字以上
- 《發作性睡病》課件
評論
0/150
提交評論