版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、網(wǎng)絡(luò)編程,IP地址與端口,TCP/IP協(xié)議層次結(jié)構(gòu),信息與封裝,TCP,IP,C/S服務(wù)模式,Winsock編程接口,Berkeley Socket,WinSock1.1,WinSock2.0,Winsock支持面向連接的通信和無連接通信兩種方式。 面向連接的編程模式 無連接的編程模式,使用socket編程需要在頭部加載Winsock2.h 并在link選項(xiàng)中的Object/library中添加Ws2_32.lib.,基于TCP的基本通信過程,服務(wù)器端: 1.加載套接字庫 2.創(chuàng)建套接字(socket) 3.將套接字綁定到一個(gè)IP地址和端口(bind) 4.將套接字設(shè)置為監(jiān)聽模式(listen
2、) 5.等待客戶請求,當(dāng)請求到來后,返回一個(gè)新的套接字用于此連接(accept) 6.用返回的套接字與客戶通信 返回等待另一請求,客戶端: 1.加載套接字庫 2.創(chuàng)建套接字(socket) 3.向服務(wù)器端發(fā)出請求(connect) 4.和服務(wù)器端進(jìn)行通信 5.發(fā)送/接收消息(send/recv) 6.關(guān)閉套接字,基于UDP的基本通信過程,服務(wù)器(接收)端: 1.加載套接字庫 2.創(chuàng)建套接字(socket) 3.將套接字綁定到一個(gè)IP地址和端口(bind) 4. 等待接收數(shù)據(jù)(recvfrom) 5.關(guān)閉套接字,客戶(發(fā)送)端: 1.加載套接字庫 2.創(chuàng)建套接字(socket) 3.向服務(wù)器端發(fā)
3、送數(shù)據(jù)(sendTo) 4.關(guān)閉套接字,加載Socket動(dòng)態(tài)庫 WS2_32.DLL ,并協(xié)商可用Socket版本 (1).int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData ) 該函數(shù)成功時(shí),返回0,否則為錯(cuò)誤代碼,1、加載Socket,其中:nVersionRequested參數(shù)用于指定要加載的Winsock庫版本,高位字節(jié)指定次版本,低位字節(jié)指定主版本??梢允褂肕AKEWORD(x,y)宏設(shè)置(x是高位字節(jié),y是低位字節(jié))。,LpWSAdata是指向WSADATA結(jié)構(gòu)的指針。該結(jié)構(gòu)的定義如下: typedef stru
4、ct WSAData WORD wVersion; /獲準(zhǔn)使用的版本 WORD wHighVersion; /該庫可以支持的最高版本 char szDescriptionWSADESCRIPTION_LEN+1; /無用 char szSystemStatusWSASYS_STATUS_LEN+1; /無用 char szSystemStatusWSASYS_STATUS_LEN+1;/無用 unsigned short iMaxSockets; /假定的可同時(shí)打開的套接字?jǐn)?shù) unsigned short iMaxUdpDg; /假定的可接受的數(shù)據(jù)報(bào)的長度 char FAR * lpVendo
5、rInfo; /無用 WSADATA, FAR * LPWSADATA; LOBYTE(wVresion)=主版本號 HIBYTE(wVresion)=次版本號,加載Socket,加載Socket,例如: WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, ,2、創(chuàng)建socket,創(chuàng)建套接字 SOCKET socket ( int af, int type, int protocol ) 該函數(shù)調(diào)用
6、成功返回一個(gè)SOCKET結(jié)構(gòu),否則返回INVALID_SOCKET ,錯(cuò)誤信息可通過 WSAGetLastError();獲得 其中: Af參數(shù)指定一個(gè)地址族,同時(shí)也指定了準(zhǔn)備使用那種協(xié)議,對于TCP/IP只能是AF_INET Type參數(shù)指定套接字的類型,一些協(xié)議只能使用某些套接字。 Protocol參數(shù)指定使用那一種具體協(xié)議。為0時(shí)自動(dòng)根據(jù)前面信息選擇協(xié)議,創(chuàng)建socket,常用的組合: 協(xié)議 地址族(af) 套接字類型(type) 協(xié)議(Protocol) IP AF_INET TCP SOCK_STREAM IPPROTO_IP UDP SOCK_DGRAM IPPROTO_UDP 例
7、如,要?jiǎng)?chuàng)建基于TCP/IP協(xié)議的套接字,則有, SOCKET s = socket(AF_INET, SOCK_STREAM,IPPROTO_IP),3、綁定地址,一臺主機(jī)可以擁有多個(gè)IP地址,綁定地址的目的是通知主機(jī),本程序在哪個(gè)IP哪個(gè)端口上監(jiān)聽 int bind ( SOCKET s,/剛創(chuàng)建的套接字 struct sockaddr FAR* name,/地址 int namelen )/地址長度,綁定地址,其中: S參數(shù)是一個(gè)套接字,表示該套接字將在name參數(shù)指定的地址名字上執(zhí)行操作。 name 參數(shù)是一個(gè)指向struct sockaddr結(jié)構(gòu)的指針。該參數(shù)隨使用的協(xié)議不同而不同。在
8、TCP/IP中常用sockaddr_in 代替: struct sockaddr_in short sin_family; /AF_INET u_short sin_port; /端口號 struct in_addr sin_addr; char sin_zero8; /填充字段 ;,綁定地址- in_addr,ip地址為四個(gè)字節(jié),為提供地址方法的靈活性,因此定義了聯(lián)合體,可以用4個(gè)字節(jié)或兩個(gè)短整數(shù)或一個(gè)長整數(shù)方式給出地址 typedef struct in_addr union struct u_char s_b1,s_b2,s_b3,s_b4 S_un_b; /4BYTE struct u
9、_short s_w1,s_w2 S_un_w; /2SHORT u_long S_addr; /1LONG S_un; in_addr; 示例: struct sockaddr_in tcpaddr; tcpaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);,綁定地址,例如, SOCKET s; int port=5150;/指定端口號要大于1024,避開常用端口 s = socket(); struct sockaddr_in tcpaddr; tcpaddr.sin_family = AF_INET; tcpaddr.sin_port = hto
10、ns(port); tcpaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); bind(s,(SOCKADDR*) 注:只有一臺機(jī)器擁有多個(gè)網(wǎng)卡(IP)時(shí),才需要指定在哪個(gè)IP監(jiān)聽,否則一般取值INADDR_ANY 此時(shí)可能需要下面兩個(gè)函數(shù) inet_addr()/點(diǎn)分十進(jìn)制字符串 to long inet_ntoa()/long to 點(diǎn)分十進(jìn)制字符串,網(wǎng)絡(luò)字節(jié)和主機(jī)字節(jié)的轉(zhuǎn)換 將主機(jī)字節(jié)轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié): u_short htons ( u_short hostshort ) u_long htonl ( u_long hostlong ) 將網(wǎng)絡(luò)字
11、節(jié)轉(zhuǎn)換為主機(jī)字節(jié): u_short ntohs ( u_short netshort ) u_long ntohl ( u_long netlong ),網(wǎng)絡(luò)字節(jié)和主機(jī)字節(jié)的轉(zhuǎn)換,等待連接,int listen( SOCKET s, int backlog ); /等待隊(duì)列最大長度,通常設(shè)為SOMAXCONN ,由系統(tǒng)決定一個(gè)合理長度,接受請求,SOCKET accept( SOCKET s, struct sockaddr* addr,/發(fā)送方的IP int* addrlen ); /需要給定初始值,然后得到確定值 例如: sockaddr_in client_addr; int len=s
12、izeof(sockaddr); while(1) SOCKET SessionSock= accept( s, (sockaddr* ) ,接收消息,int recv( SOCKET s, char* buf, int len, int flags ); /通常設(shè)為0,int send( SOCKET s, const char* buf, int len, int flags );,關(guān)閉與卸載,當(dāng)Socket不再使用時(shí): int closesocket( SOCKET s ); 程序退出前,卸載Winsock庫 int WSACleanup(),客戶端的過程,1、加載Socket DLL
13、2、創(chuàng)建Socket 3、請求連接 int connect( SOCKET s, const struct sockaddr* name, /服務(wù)器IP int namelen ); 4、斷開連接 5、卸載Winsock,單線程TCP通信程序示例與分析,實(shí)例:TcpDemo 分析: 由于單線程的原因,服務(wù)器端同時(shí)只能為一個(gè)用戶服務(wù),必須等一個(gè)用戶釋放連接后才能接受下一個(gè)用戶的請求 由于不是Windows中的消息驅(qū)動(dòng)機(jī)制,收發(fā)次序由程序決定,沒有收到信息時(shí),不能發(fā)送,就相當(dāng)于“一個(gè)人聊天時(shí)只能應(yīng)答,不能主動(dòng)發(fā)言”,基于UDP的通信-接收端,1、加載套接字庫 2、創(chuàng)建套接字 SOCKET sock
14、Srv=socket(AF_INET,SOCK_DGRAM,0); 3、綁定監(jiān)聽地址 4、等待接收recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*),基于UDP的通信-發(fā)送端,1、加載套接字庫 2、創(chuàng)建套接字 SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0); 3、發(fā)送數(shù)據(jù) sendto(sockClient,Hello,strlen(Hello)+1,0, (SOCKADDR*),UDP完成一次發(fā)送過程示例,示例:UdpDemo 分析:此例只能完成一次單向的信息傳送,如果要做到對話,必須雙方都建立發(fā)送SOCKET和
15、接收SOCKET 只能使用IP地址,而不能使用主機(jī)名,名字解析,各協(xié)議族都有自己地址解析機(jī)制。 IP網(wǎng)絡(luò)的地址解析函數(shù): gethostbyaddr 該函數(shù)根據(jù)IP地址得到主機(jī)名。 HOSTENT FAR * gethostbyaddr ( const char FAR * addr, /指向要查找的IP地址 int len, /addr的長度 int type /類型,為 AF_INET );,名字解析,gethostbyname 該函數(shù)根據(jù)主機(jī)名得到IP地址。 struct hostent FAR * gethostbyname ( const char FAR * name /指向要查找
16、的主機(jī)名 ) 該函數(shù)返回struct hostent結(jié)構(gòu)。,struct hostent,struct hostent char FAR *h_name; /是正式的主機(jī)名 char FAR * FAR * h_aliases; /是由主機(jī)備用名組成的數(shù)組 short h_addrtype; /表示返回的地址族 short h_length; / h_addr_list參數(shù)的長度 char FAR * FAR * h_addr_list; /是用由主機(jī)IP地址組成的列表,是網(wǎng)絡(luò)字節(jié) ;,名字解析,gethostname 得到本地主機(jī)名 int gethostname ( char FAR *
17、name, int namelen ) inet_addr將IP地址的點(diǎn)分格式轉(zhuǎn)換為正確的IN_ADDR結(jié)構(gòu)。 unsigned long inet_addr ( const char FAR * cp ) inet_ntoa 將Internet IP地址轉(zhuǎn)換為點(diǎn)分格式 char FAR * inet_ntoa ( struct in_addr in ),名字解析示例,WSADATA lpd; char HostName101,*p; struct in_addr in; HOSTENT *h; unsigned long *pp; WSAStartup(MAKEWORD(2,2),阻塞模式與
18、非阻塞模式,Windows套接字在兩種模式下執(zhí)行I/O操作:阻塞模式與非阻塞模式,在阻塞模式下,等待接受不能繼續(xù)執(zhí)行,一般采用多線程方式編程,以解決進(jìn)程的等待問題。,阻塞模式下多線程解決方案,啟動(dòng): listen(ListenSock,5); AfxBeginThread( . ,非阻塞模式:,通過控制套接字函數(shù) int ioctlsocket ( SOCKET s, long cmd, /控制標(biāo)志,F(xiàn)IONBIO:清楚阻塞標(biāo)記 u_long FAR* argp )/ 0:cmd Disable 1: cmd Enable 將一個(gè)套接字設(shè)置為非鎖定模式。,非阻塞模式:,例如, unsigned
19、 int ul=1;/ul非0值非阻塞模式 s = socket(AF_INET,SOCK_STREAM,0); ioctlsocket(s, FIONBIO , (unsigned long *) 在Winsock中共有5種套接字I/O模型:選擇模型、異步選擇模型、事件選擇模型、重疊模型和完成端口模型。,選擇模型(Select),中心是利用select()函數(shù),通過該函數(shù)可以判斷套接字上是否存在可讀的數(shù)據(jù),或能否向一個(gè)套接字寫入數(shù)據(jù)。該函數(shù)的目的是防止應(yīng)用程序在套接字處于鎖定模式時(shí),在一次I/O調(diào)用中,進(jìn)入鎖定狀態(tài)。,select函數(shù)的格式如下:,int select ( int nfds,
20、 /被忽略 fd_set FAR * readfds,/檢查可讀性,是否有可讀的數(shù)據(jù) fd_set FAR * writefds,/檢查可寫性,是否有可寫的數(shù) fd_set FAR * exceptfds,/檢查是否有帶外數(shù)據(jù) const struct timeval FAR * timeout /struct timeval的指針,確定該函數(shù)執(zhí)行的等待時(shí)間,當(dāng)為NULL時(shí),無限期等待,直到有一個(gè)滿足的條件返回),select函數(shù)參數(shù)說明,fd_set是一個(gè)集合,常用的操作宏: FD_CLR(s,*set): 從set中刪除s FD_ISSET(s,*set): 檢查s是否是set的一個(gè)元素。
21、 FD_SET(s,*set): 將s加入set FD_ZERO(*set): 將set初始化為空集合 struct timeval long tv_sec; /以秒為單位指定時(shí)間 long tv_usec; /以毫秒為單位指定時(shí)間 ;,select舉例,SOCKET s; fd_set fds; int ret; while(1) FD_ZERO( If(ret=SOCKET_ERROR) /Error else if(FD_ISSET(s, HWND hWnd; s=socket(); WSAAsyncSelect(s,hWnd,WM_SOCKET, FD_ACCEPT|FD_CLOSE)
22、; ,WSAAsyncSelect舉例,BOOL CALLBACK WndProc(HWND hWnd, UINT uMsg,WPARAM wParam,LPARAM lParam) SOCKET Accept; Switch(uMsg) case WM_SOCKET:/自定義的消息 if(WSAGETSELECTERROR(lParam) closesocket(wParam); break; switch(WSAGETSELECTEVENT(lParam) case FD_ACCEPT: case FD_CLOSE: ,WSAAsyncSelect完整示例,ChatRome,MFC中的Winsock,主要有CAsyncSocket和CSocket類。 CasyncSocket類封裝了Winsock API,和Winsock編程的方法幾乎一樣。CS
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 園林公司財(cái)務(wù)制度管理
- 電動(dòng)車生產(chǎn)企業(yè)財(cái)務(wù)制度
- 職業(yè)教育機(jī)構(gòu)財(cái)務(wù)制度
- 農(nóng)村信用社會計(jì)基本制度
- 公路科技創(chuàng)新制度
- 養(yǎng)老院老人康復(fù)設(shè)施維修人員職業(yè)道德制度
- 醫(yī)院自備藥物管理制度培訓(xùn)(3篇)
- 內(nèi)墻大白施工方案(3篇)
- 打樁斜壓施工方案(3篇)
- 沖砂涵洞施工方案(3篇)
- 2026年哈爾濱通河縣第一批公益性崗位招聘62人考試參考試題及答案解析
- 六年級寒假家長會課件
- 物流鐵路專用線工程節(jié)能評估報(bào)告
- 2026天津市南開區(qū)衛(wèi)生健康系統(tǒng)招聘事業(yè)單位60人(含高層次人才)備考核心試題附答案解析
- 重瞼手術(shù)知情同意書
- 研發(fā)部門員工加班管理細(xì)則
- 46566-2025溫室氣體管理體系管理手冊及全套程序文件
- 九師聯(lián)盟2026屆高三上學(xué)期12月聯(lián)考英語(第4次質(zhì)量檢測)(含答案)
- 第21章 反比例函數(shù)(單元測試·綜合卷)(含答案)-滬科版(2024)九上
- 鋼結(jié)構(gòu)橋梁施工監(jiān)測方案
- 2025年秋青島版(五四學(xué)制)小學(xué)數(shù)學(xué)五年級上冊(全冊)知識點(diǎn)梳理歸納
評論
0/150
提交評論