要實(shí)現(xiàn)網(wǎng)絡(luò)編程,有多種方法通過WinSock、所用命名管_第1頁
要實(shí)現(xiàn)網(wǎng)絡(luò)編程,有多種方法通過WinSock、所用命名管_第2頁
要實(shí)現(xiàn)網(wǎng)絡(luò)編程,有多種方法通過WinSock、所用命名管_第3頁
要實(shí)現(xiàn)網(wǎng)絡(luò)編程,有多種方法通過WinSock、所用命名管_第4頁
要實(shí)現(xiàn)網(wǎng)絡(luò)編程,有多種方法通過WinSock、所用命名管_第5頁
已閱讀5頁,還剩69頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、要實(shí)現(xiàn)網(wǎng)絡(luò)編程,有多種方法:WinSock、所用命名管道和郵箱、使用RPC(Remote Procedure Call)等均可以實(shí)現(xiàn)在網(wǎng)絡(luò)上的通信。本講將介紹利用WinSock編程的兩種途徑:一種是通過WinSock API另一種是通過MFC 提供的WinSock類,即 CAsyncSocket和CSocket前言1Windows Socket編程原理2Socket概述Socket簡介Windows Socket Winsock1.1基本APIWinsock2.0CAsyncSocketCSocket3什么是socket?應(yīng)用程序與網(wǎng)絡(luò)之間的接口應(yīng)用程序創(chuàng)建socketsocket 類型 決定

2、了通信的類型可靠的 vs. 盡最大努力的面向連接的 vs. 無連接的一旦socket配置完成,應(yīng)用程序就可以把數(shù)據(jù)傳給socket,從而進(jìn)行網(wǎng)絡(luò)傳輸從socket接收數(shù)據(jù)(其他主機(jī)通過網(wǎng)絡(luò)發(fā)送過來的)Socket在計(jì)算機(jī)中提供了一個(gè)通信接口,可以通過這個(gè)接口與任何一個(gè)具有Socket接口的計(jì)算機(jī)通信。應(yīng)用程序在網(wǎng)絡(luò)上傳輸,接收的信息都通過這個(gè)Socket接口來實(shí)現(xiàn)。 4Socket在協(xié)議棧中的位置ApplicationTransportNetwork(Internet)Data-link(Host-to-Network)Sockets APITCPUDPMyProgramIP5Socket到S

3、ocket的通信My ProgramsocketportsTCP/UDPIPYour ProgramsocketportsTCP/UDPIP6Windows Socket(1)Windows Socket 是從 Berkeley Socket擴(kuò)展而來的,其在繼承 Berkeley Socket的基礎(chǔ)上,又進(jìn)行了新的擴(kuò)充。這些擴(kuò)充主要是提供了一些異步函數(shù),并增加了符合Windows消息驅(qū)動(dòng)特性的網(wǎng)絡(luò)事件異步選擇機(jī)制 Windows socket的版本W(wǎng)insock1.1Winsock2.07Windows Socket(2)Winsock的實(shí)現(xiàn)方式Winsock: C-Based API, 與U

4、nix C API類似CAsyncSocket: 對(duì)Winsock API的簡單C+封裝CSocket: 對(duì)Socket的高層抽象 (自動(dòng)處理字節(jié)順序轉(zhuǎn)換等)對(duì)象串行化CSocketFileCArchive8端口Port 0Port 1Port 65535每個(gè)主機(jī)有65,536個(gè)端口一些端口被預(yù)留,用于特定的應(yīng)用程序20,21: FTP23: Telnet80: HTTP參考RFC 1700 (大約1024個(gè)端口被預(yù)留)Socket提供了一個(gè)通過端口在網(wǎng)絡(luò)上收發(fā)數(shù)據(jù)的接口9TCP/IP約定:01023為保留端口號(hào),標(biāo)準(zhǔn)應(yīng)用服務(wù)使用;1024以上是自由端口號(hào),用戶應(yīng)用服務(wù)使用 端口號(hào)實(shí)質(zhì)上也是操

5、作系統(tǒng)標(biāo)識(shí)應(yīng)用程序的一種方法,其取值可由用戶定義或者系統(tǒng)分配 10IP地址、端口和Socket類似公寓和郵箱你是應(yīng)用程序你的公寓地址是地址你的郵箱是端口郵局是網(wǎng)絡(luò)Socket是使你能夠使用郵箱的鑰匙(假設(shè)發(fā)出去的信是由你放入郵箱的)Script: Socket(48)=IP地址(32)+端口(16)11TCP/IP應(yīng)用服務(wù)工作原理采用客戶機(jī)/服務(wù)器模式服務(wù)器端啟動(dòng)守護(hù)進(jìn)程,等待客戶端的請(qǐng)求;服務(wù)器對(duì)應(yīng)客戶端的請(qǐng)求,派生子進(jìn)程與客戶進(jìn)程進(jìn)行數(shù)據(jù)通信,提供服務(wù)。服務(wù)器擁有全局公認(rèn)的Socket ,接收任何客戶端的請(qǐng)求。12Socket工作原理API函數(shù)CAsyncSocketCSocket13So

6、cket的系統(tǒng)調(diào)用庫函數(shù)1、創(chuàng)建套接字 Sockid=Socket(af,type,protocol) 2、建立地址和套接字的聯(lián)系 bind(sockid, local addr, addrlen) 3、服務(wù)器端偵聽客戶端的請(qǐng)求 listen( Sockid ,quenlen) 4、建立服務(wù)器/客戶端的連接 (面向連接TCP) 客戶端請(qǐng)求連接 Connect(sockid, destaddr, addrlen) 服務(wù)器端等待從編號(hào)為Sockid的Socket上接收客戶連接請(qǐng)求 newsockid=accept(Sockid,Clientaddr, paddrlen) 5、發(fā)送/接收數(shù)據(jù) 面向連

7、接:send(sockid, buff, bufflen) recv( ) 面向無連接:sendto(sockid,buff,addrlen) recvfrom( ) 6、釋放套接字 close(sockid)14API的使用方法圖示15分身有術(shù)被動(dòng)參與者step 1: listen (監(jiān)聽連接請(qǐng)求)step 3: accept (接受連接請(qǐng)求)step 4: 數(shù)據(jù)傳輸被接受的連接工作在新的Socket上舊Socket繼續(xù)監(jiān)聽其他的主動(dòng)參與者主動(dòng)參與者step 2: 請(qǐng)求并建立連接step 4: 數(shù)據(jù)傳輸Passive Participantl-socka-sock-1a-sock-2Acti

8、ve 1socketActive 2socket16#include struct sockaddr_inshort sin_family;/AF_INETunsigned short sin_port;/16位端口號(hào),網(wǎng)絡(luò)字節(jié)順序struct in_addr sin_addr; /32位IP地址,網(wǎng)絡(luò)字節(jié)順序char sin_zero8;/保留;Internet地址數(shù)據(jù)結(jié)構(gòu)sin_family = AF_INET 選擇Internet地址族17字節(jié)順序問題:不同的機(jī)器使用不同的字節(jié)順序小頭: 低字節(jié)優(yōu)先 i386, alpha, .大頭: 高字節(jié)優(yōu)先 Sun Solaris, PowerPC

9、, .使用不同字節(jié)順序的主機(jī)如何通過網(wǎng)絡(luò)通信21281194012281281194012大頭主機(jī)小頭主機(jī)WRONG!18解決方法:網(wǎng)絡(luò)字節(jié)順序定義:主機(jī)字節(jié)順序: 主機(jī)使用的字節(jié)順序 (大頭或小頭) Sun Solaris, PowerPC, .網(wǎng)絡(luò)字節(jié)順序:網(wǎng)絡(luò)使用的字節(jié)順序大頭通過網(wǎng)絡(luò)傳輸?shù)娜魏涡畔⒍紤?yīng)該轉(zhuǎn)化成網(wǎng)絡(luò)字節(jié)順序 ,接收后再轉(zhuǎn)回主機(jī)字節(jié)順序Q: Socket是否自動(dòng)完成字節(jié)順序轉(zhuǎn)換?Q: 大頭主機(jī)不需要轉(zhuǎn)換字節(jié)順序,而小頭主機(jī)需要,如何避免寫兩個(gè)版本的代碼?19字節(jié)順序轉(zhuǎn)換函數(shù)在主機(jī)字節(jié)順序和網(wǎng)絡(luò)字節(jié)順序之間轉(zhuǎn)換h = 主機(jī)字節(jié)順序n = 網(wǎng)絡(luò)字節(jié)順序l = long (4 b

10、ytes), 轉(zhuǎn)換IP地址s = short (2 bytes), 轉(zhuǎn)換端口號(hào)#include u_long PASCAL FAR htonl( u_long hostlong); u_short PASCAL FAR htons( u_short hostshort); u_long PASCAL FAR ntohl( u_long netlong); u_short PASCAL FAR ntohs( u_short netshort);在大頭主機(jī)上,上述函數(shù)不作任何轉(zhuǎn)換在小頭主機(jī)上,上述函數(shù)把字節(jié)順序逆序Same code would have worked regardless of

11、endian-ness of the two machines20Socket的兩種基本類型SOCK_STREAMTCP可靠傳輸保證順序面向連接雙向SOCK_DGRAMUDP不可靠傳輸無順序保證無“連接”概念 應(yīng)用程序?yàn)槊總€(gè)包指定目的地可以發(fā)送或接收Appsocket321Dest.Appsocket321D1D3D2Q: 為什么需要 SOCK_DGRAM類型?21TCPIPEthernet AdapterWeb ServerPort 80舉例: web server為了接收來自web client的連接請(qǐng)求,web server應(yīng)做什么準(zhǔn)備?TCP Server22每個(gè)Winsock應(yīng)用都必

12、須加載Winsock DLL的相應(yīng)版本#include int PASCAL FAR WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData ); wVersionRequested:Windows Socket API提供的調(diào)用方可使用的最高版本號(hào).高位字節(jié)指出副版本(修正)號(hào),低位字節(jié)指明主版本號(hào). lpWSAData:指向WSADATA數(shù)據(jù)結(jié)構(gòu)的指針,用來接收Windows Socket實(shí)現(xiàn)的細(xì)節(jié).Winsock的初始化WSADATA wsd;if(WSAStartup(MAKEWORD(1,1),&wsd)!=0)return

13、FALSE;23Web使用TCP, web server需要?jiǎng)?chuàng)建一個(gè)SOCK_STREAM套接字#include SOCKET PASCAL FAR socket( int af, int type, int protocol);af:一個(gè)地址格式描述。type:新套接字的類型描述。protocol:套接字所用的協(xié)議。如調(diào)用者不想指定,可用0。Socket I/O: socket()SOCKET m_hSocket;m_hSocket=socket(AF_INET,SOCK_STREAM,0);AF_INET 把socket與Internet協(xié)議族相關(guān)聯(lián)SOCK_STREAM 選擇 TCP協(xié)議

14、24把socket 綁定到一個(gè)特定端口int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen);s: 標(biāo)識(shí)一未捆綁套接字的描述字。name:賦予套接字的地址。 返回值:沒有錯(cuò)誤,bind()返回0,否則返回SOCKET_ERRORSocket I/O: bind()sockaddr_in m_addr;m_addr.sin_family = AF_INET;m_addr.sin_addr.S_un.S_addr =htonl(INADDR_ANY);m_addr.sin_port = htons(8

15、0);int ret = 0;int error = 0;ret = bind(m_hSocket, (LPSOCKADDR)&m_addr, sizeof(m_addr);if(ret = SOCKET_ERROR)AfxMessageBox(Binding Error); /綁定錯(cuò)誤return FALSE;25Socket I/O: listen()listen 表示 server準(zhǔn)備接收連接請(qǐng)求#include int PASCAL FAR listen( SOCKET s, int backlog); S:用于標(biāo)識(shí)一個(gè)已捆綁未連接套接字的描述字。 backlog:等待連接隊(duì)列的最大長

16、度。 ret = listen(m_hSocket, 5); /第二個(gè)參數(shù)表示最多支持的客戶連接數(shù)if(ret = SOCKET_ERROR)/listen失敗AfxMessageBox(Listen Error);return FALSE;26Socket I/O: accept()accept 等待一個(gè)連接請(qǐng)求#include SOCKET PASCAL FAR accept( SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen); s:套接字描述字,該套接字在listen()后監(jiān)聽連接。 addr:(可選)指針,指向一緩沖區(qū),接收連

17、接實(shí)體的地址。Addr參數(shù)的實(shí)際格式由套接字創(chuàng)建時(shí)所產(chǎn)生的地址族確定。 addrlen:(可選)指針,指向存有addr地址長度的整形數(shù)。 返回值:返回一個(gè)新的socket,其屬性與s相同。若返回值0,則表明發(fā)生了錯(cuò)誤。27Socket I/O: accept()#include SOCKET socket;struct sockaddr cli;int cli_len = sizeof(cli);socket= accept(m_hSocket, &cli, &cli_len);if(socket 0) AfxMessageBox(Listen Error);return FALSE;Serv

18、er如何得到Client的基本信息?cli.sin_addr.s_addr 包含了client的IP地址cli.sin_port 包含了Client的端口號(hào)accept 為什么要返回一個(gè)新的socket?28Socket I/O: recv()recv 可以從一個(gè)socket接收數(shù)據(jù)。#include int PASCAL FAR recv( SOCKET s, char FAR* buf, int len, int flags); s:一個(gè)標(biāo)識(shí)已連接套接字的描述字。 buf:用于接收數(shù)據(jù)的緩沖區(qū)。 len:緩沖區(qū)長度。 flags:指定調(diào)用方式。 返回值:若無錯(cuò)誤發(fā)生,recv()返回讀入的

19、字節(jié)數(shù)。如果連接已中止,返回0。否則返回SOCKET_ERROR錯(cuò)誤。 #include char s1024;int len;len=recv(socket,s,1024,0); 29TCPIPEthernet Adapter2 Web ClientsTCP Client舉例: web clientweb client 如何連接到一個(gè)web server? 30#include unsigned long PASCAL FAR inet_addr( const struct FAR* cp); cp:一個(gè)以Internet標(biāo)準(zhǔn)“.”間隔的字符串。 返回值:若無錯(cuò)誤發(fā)生,返回一個(gè)無符號(hào)長整型數(shù)

20、。如果傳入的字符串不是一個(gè)合法的Internet地址,那么返回INADDR_NONE。 struct sockaddr_in srv;srv.sin_addr.s_addr = inet_addr(“0”);將數(shù)值地址轉(zhuǎn)化成字符串地址:處理IP地址IP地址通常表示為字符串 (“0”),但程序把IP地址作為整數(shù)來處理。#include char FAR* PASCAL FAR inet_ntoa( struct in_addr in); in:一個(gè)表示Internet主機(jī)地址的結(jié)構(gòu)。將字符串地址轉(zhuǎn)化成數(shù)值地址:31把域名轉(zhuǎn)換成地址gethostname 獲得本地主機(jī)名gethostbyname

21、為DNS提供接口,從主機(jī)名得到對(duì)應(yīng)的主機(jī)地址。gethostbyaddr 由網(wǎng)絡(luò)地址得到對(duì)應(yīng)的主機(jī)信息。struct hostent *hp; struct sockaddr_in peeraddr;char *name = “”;peeraddr.sin_family = AF_INET; hp = gethostbyname(name) peeraddr.sin_addr.s_addr = (struct in_addr*)(hp-h_addr_list0)-s_addr;struct hostent char FAR* h_name; char FAR FAR* h_aliases; s

22、hort h_addrtype; short h_length; char FAR FAR* h_addr_list; ;32Socket I/O: connect()connect client連接到server#include int PASCAL FAR connect( SOCKET s, const struct sockaddr FAR* name, int namelen); s:標(biāo)識(shí)一個(gè)未連接套接字的描述字。 name:欲進(jìn)行連接的端口名。 namelen:名字長度。 返回值:若無錯(cuò)誤發(fā)生,則connect()返回0。否則的話,返回SOCKET_ERROR錯(cuò)誤。 int ret

23、 = 0;ret = connect(m_hSocket, (LPSOCKADDR)&m_addr, sizeof(m_addr);if(ret = SOCKET_ERROR)AfxMessageBox(“連接失敗”);return FALSE;33Socket I/O: send()send 向一個(gè)已連接的socket發(fā)送數(shù)據(jù)#include int PASCAL FAR send( SOCKET s, const char FAR* buf, int len, int flags); s:一個(gè)用于標(biāo)識(shí)已連接套接字的描述字。 buf:包含待發(fā)送數(shù)據(jù)的緩沖區(qū)。 len:緩沖區(qū)中數(shù)據(jù)的長度。 f

24、lags:調(diào)用執(zhí)行方式。 返回值:若無錯(cuò)誤發(fā)生,返回所發(fā)送數(shù)據(jù)的總數(shù),否則返回SOCKET_ERROR錯(cuò)誤。 if(send(m_hSocket,buf,strlen(buf),0)=SOCKET_ERROR) AfxMessageBox(Send data error);34Socket I/O: closesocket()closesocket 關(guān)閉一個(gè)socket#include int PASCAL FAR closesocket( SOCKET s); s:一個(gè)套接字的描述字。 返回值:如無錯(cuò)誤發(fā)生,則返回0,否則返回SOCKET_ERROR錯(cuò)誤。 35TCP Client-Serv

25、er交互流程socket()bind()listen()accept()send()recv()recv()TCP Serverclosesocket()socket()TCP Clientconnect()send()recv()closesocket()建立連接請(qǐng)求數(shù)據(jù)響應(yīng)數(shù)據(jù)文件結(jié)束標(biāo)識(shí)36tcp_server.c#include #define MY_PORT 3434int main() SOCKET listen_sock, new_sock;struct sockaddr_in my_addr;int dummy;char *buffer =How old are you?n;W

26、SADATA wsaData;WSAStartup(MAKEWORD(1,1),&wsaData);listen_sock = socket(AF_INET, SOCK_STREAM, 0); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MY_PORT); my_addr.sin_addr.s_addr = INADDR_ANY; bind(listen_sock, (struct sockaddr *)&my_addr, sizeof(struct sockaddr);listen(listen_sock, 5);new_so

27、ck = accept(listen_sock, NULL, &dummy);send(new_sock, buffer, strlen(buffer), 0);closesocket(new_sock);closesocket(listen_sock);WSACleanup();return 0;37tcp_client.c#include #include #define MY_PORT 3434int main() SOCKET conn_sock;struct sockaddr_in remote_addr;int bytes_recvd;char buffer100;WSADATA

28、wsaData;WSAStartup(MAKEWORD(1,1),&wsaData);conn_sock = socket(AF_INET, SOCK_STREAM, 0); remote_addr.sin_family = AF_INET; remote_addr.sin_port = htons(MY_PORT); remote_addr.sin_addr.s_addr = inet_addr(8); connect(conn_sock, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr);bytes_recvd = recv(

29、conn_sock, buffer, sizeof(buffer), 0);printf(Received (%d bytes): %sn, bytes_recvd, buffer);closesocket(conn_sock);WSACleanup();return 0;38UDPIPEthernet AdapterNTPdaemonUDP ServerPort 123舉例: NTP daemon為了接收來自UDP client的服務(wù)請(qǐng)求,UDP server應(yīng)做什么準(zhǔn)備?39Socket I/O: socket()UDP server必須創(chuàng)建一個(gè)datagram socketSOCKET

30、m_hSocket;m_hSocket=socket(AF_INET,SOCK_DGRAM,0);AF_INET 把socket與Internet協(xié)議族相關(guān)聯(lián)SOCK_DGRAM 選擇UDP協(xié)議40把socket 綁定到一個(gè)特定端口Socket I/O: bind()sockaddr_in m_addr;m_addr.sin_family = AF_INET;m_addr.sin_addr.S_un.S_addr =htonl(INADDR_ANY);m_addr.sin_port = htons(123);int ret = 0;int error = 0;ret = bind(m_hSoc

31、ket, (LPSOCKADDR)&m_addr, sizeof(m_addr);if(ret = SOCKET_ERROR)AfxMessageBox(Binding Error); /綁定錯(cuò)誤return FALSE;41Socket I/O: recvfrom()recvfrom 接收一個(gè)數(shù)據(jù)報(bào)并保存源地址#include int PASCAL FAR recvfrom( SOCKET s, char FAR* buf, int len, int flags,struct sockaddr FAR* from, int FAR* fromlen); s:標(biāo)識(shí)一個(gè)套接字的描述字。 buf:

32、接收數(shù)據(jù)緩沖區(qū)。 len:緩沖區(qū)長度。 flags:調(diào)用操作方式。 from:(可選)指針,指向裝有源地址的緩沖區(qū)。 fromlen:(可選)指針,指向from緩沖區(qū)長度值。 返回值:若無錯(cuò)誤發(fā)生,返回讀入的字節(jié)數(shù)。如果連接已中止,返回0。否則返回SOCKET_ERROR錯(cuò)誤。42Socket I/O: recvfrom()SOCKET srvsock;sockaddr cli;char buf512;int cli_len = sizeof(cli); int nbytes;nbytes = recvfrom(srvsock, buf, sizeof(buf), 0 , (struct so

33、ckaddr*) &cli, &cli_len);if(nbytes 0) AfxMessageBox(“接收數(shù)據(jù)失敗”);return FALSE;43UDPIPEthernet Adapter2 UDP ClientsUDP ClientportsUDP client 如何與UDP server通信?44Socket I/O: sendto()UDP client 不與特定端口號(hào)綁定第一次調(diào)用sendto時(shí),動(dòng)態(tài)為其分配一個(gè)端口號(hào)SOCKET clisock;char buf512;int nbytes;sockaddr_in m_addr;m_addr.sin_family = AF_I

34、NET;m_addr.sin_addr.S_un.S_addr =inet_addr(“0”);m_addr.sin_port = htons(123);nbytes = sendto(clisock, buf, sizeof(buf),0, (struct sockaddr*) &m_addr, sizeof(m_addr);if(nbytes 0) AfxMessageBox(“發(fā)送數(shù)據(jù)失敗”);return FALSE;45UDP Client-Server交互流程socket()bind()recvfrom()sendto()UDP Serversocket()UDP Clientse

35、ndto()recvfrom()closesocket()等待,直到從client接收到數(shù)據(jù)報(bào)數(shù)據(jù)請(qǐng)求數(shù)據(jù)響應(yīng)46udp_server.c#include #define MY_PORT 3434int main() SOCKET udp_sock; struct sockaddr_in remote_addr, local_addr; char *buffer = How do you do?; WSADATA wsaData; WSAStartup(MAKEWORD(1,1),&wsaData); udp_sock = socket(AF_INET, SOCK_DGRAM, 0); loc

36、al_addr.sin_family = AF_INET; local_addr.sin_port = htons(MY_PORT); local_addr.sin_addr.s_addr = INADDR_ANY; bind(udp_sock, (sockaddr *)&local_addr, sizeof(struct sockaddr_in); remote_addr.sin_family = AF_INET; remote_addr.sin_port = htons(MY_PORT); remote_addr.sin_addr.s_addr = inet_addr(8); for (i

37、nt i = 0; i 10; i+) sendto(udp_sock, buffer, strlen(buffer), 0, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr_in); closesocket(udp_sock); WSACleanup(); return 0;47udp_client.c#include #include #define MY_PORT 3434int main() SOCKET udp_sock; struct sockaddr_in remote_addr, local_addr; int b

38、ytes_recvd, dummy; char buffer100; WSADATA wsaData; WSAStartup(MAKEWORD(1,1),&wsaData); udp_sock = socket(AF_INET, SOCK_DGRAM, 0); local_addr.sin_family = AF_INET; local_addr.sin_port = htons(MY_PORT); local_addr.sin_addr.s_addr = INADDR_ANY; bind(udp_sock, (sockaddr *)&local_addr, sizeof(struct soc

39、kaddr_in); bytes_recvd = recvfrom(udp_sock, buffer, sizeof(buffer), 0, NULL, &dummy); bufferbytes_recvd = 0; printf(Received (%d bytes): %sn, bytes_recvd, buffer); closesocket(udp_sock); WSACleanup(); return 0;48Winsock2.0Winsock2.0是對(duì)winsock1.1的升級(jí)支持多種傳輸協(xié)議TCP/IP、IPX/SPX、ATM、NETBIOS、AppleTalk、紅外線重疊I/O

40、和事件對(duì)象服務(wù)質(zhì)量套接字組共享套接字協(xié)議無關(guān)的多播通信49CAsyncSocket編程50CAsyncSocketCAsyncSocket 在低層次上封裝了Winsock API,簡化網(wǎng)絡(luò)消息回調(diào)函數(shù)的編寫。用戶需要自己處理阻塞、字節(jié)順序等問題CAsyncSocket類封裝了大部分Winsock APIServer:Create()把socket()和bind()綁定在一起Listen()Accept()Client:Create()Connect()參見書p8位置51CAsyncSocket程序流程使用CAsyncSocket的網(wǎng)絡(luò)應(yīng)用程序結(jié)構(gòu)創(chuàng)建 socketServerClient編寫回

41、調(diào)函數(shù)以便接收數(shù)據(jù)發(fā)送數(shù)據(jù)關(guān)閉socket用MFC構(gòu)建使用CAsyncSocket的網(wǎng)絡(luò)程序的步驟如右圖用AppWizard創(chuàng)建應(yīng)用程序框架派生CAsyncSocket的子類重載成員函數(shù)來處理Winsock 消息等待并處理Winsock 消息激活Winsock消息52用AppWizard創(chuàng)建應(yīng)用程序框架(1)在MFC AppWizard中指定支持Winsock53CAsyncSocketAppWizard 產(chǎn)生的Winsock 啟動(dòng)代碼BOOL CWinsockApp:InitInstance()if (!AfxSocketInit()AfxMessageBox(IDP_SOCKETS_INI

42、T_FAILED);return FALSE;.AfxSocketInit( )WSAStartup( )調(diào)用用AppWizard創(chuàng)建應(yīng)用程序框架(1)54派生CAsyncSocket類(2)CAsyncSocket派生CAsyncSocket的一個(gè)子類CAsyncSocketCAppSocketderive55CAsyncSocket: 生成的CAppSocket類 (AppSocket.h)class CAppSocket : public CAsyncSocket/ Attributespublic:/ Operationspublic: CAppSocket(); virtual CA

43、ppSocket();/ Overridespublic: / ClassWizard generated virtual function overrides /AFX_VIRTUAL(CAppSocket) /AFX_VIRTUAL / Generated message map functions /AFX_MSG(CAppSocket) / NOTE - the ClassWizard will add and remove member functions here. /AFX_MSG/ Implementationprotected:;派生CAsyncSocket類(2)56添加處

44、理Winsock事件的代碼(3)57class CAppSocket : public CAsyncSocket. / ClassWizard generated virtual function overrides /AFX_VIRTUAL(CAppSocket) public: virtual void OnReceive(int nErrorCode); /AFX_VIRTUAL.;AppSocket.hvoid CAppSocket:OnReceive(int nErrorCode) / TODO: Add your specialized code here / and/or cal

45、l the base class CAsyncSocket:OnReceive(nErrorCode);AppSocket.cpp添加處理Winsock事件的代碼(3)58激活Winsock事件(4)CAsyncSocket: 激活Winsock事件重載通知函數(shù) BOOL CAsyncSocket:AsyncSelect( long lEvent); lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSEonReceive()當(dāng)有數(shù)據(jù)要接收時(shí)的調(diào)用onSend()準(zhǔn)備好發(fā)送數(shù)據(jù)時(shí)調(diào)用onAccept()可

46、以接受連接請(qǐng)求時(shí)調(diào)用onConnect()當(dāng)建立連接時(shí)調(diào)用onClose() 當(dāng)socket關(guān)閉時(shí)調(diào)用59CAsyncSocket的成員函數(shù)Accept接收連接AsyncSelect設(shè)置socket的事件通知Bind為socket綁定地址Close關(guān)閉 socket.Connect建立連接IOCtl控制socket的模式Listen監(jiān)聽連接請(qǐng)求Receive從socket接收數(shù)據(jù)ReceiveFrom接收數(shù)據(jù)報(bào),并保存源地址Send向建立連接的socket發(fā)送數(shù)據(jù)SendTo向特定地址發(fā)送數(shù)據(jù)ShutDown禁止socket上的Send和/或Receive調(diào)用60CAsyncSocket構(gòu)造一

47、個(gè)CAsyncSocket對(duì)象Create創(chuàng)建一個(gè)socket.Attach把一個(gè)socket handle關(guān)聯(lián)到一個(gè)CAsyncSocket對(duì)象Detach取消socket handle與一個(gè)CAsyncSocket對(duì)象之間的關(guān)聯(lián)FromHandle給定一個(gè)socket handle,返回一個(gè)指向CAsyncSocket對(duì)象的指針GetLastError得到最后一個(gè)錯(cuò)誤操作的錯(cuò)誤狀態(tài)GetPeerName得到建立連接的socket的地址GetSockName得到一個(gè)socket的名字GetSockOpt得到一個(gè)socket的選項(xiàng)SetSockOpt設(shè)置一個(gè)socket的選項(xiàng)CAsyncSoc

48、ket的成員函數(shù)61CSocket編程62封裝了使用socket時(shí)的所有細(xì)節(jié),包括網(wǎng)絡(luò)字節(jié)順序,主機(jī)名解析和地址族等。WinSockCAsyncSocket (MFC)與物理網(wǎng)絡(luò)的距離CSocket (MFC)CSocket簡介63CSocket ServerCSocket ClientCSocket ServSocket;ServSocket.Create(8080);CSocket socket;socket.Create( );ServSocket.Listen( );socket.Connect(“aHost”,8080);初始化一個(gè)socket,使用 8080初始化一個(gè) socket

49、,使用任意端口連接到主機(jī) “aHost” 的端口8080監(jiān)聽連接請(qǐng)求CSocket socket;ServSocket.Accept(socket);用socket處理連接請(qǐng)求使用CSocket的過程(1)64建立連接后的一對(duì)CSocket可以用Send和Receive兩個(gè)成員函數(shù)進(jìn)行可靠的通信SendReceive使用CSocket的過程(2)65使用CSocket傳輸C+對(duì)象MFC提供了在 socket連接上串行化對(duì)象的方法Archive。把CSocket對(duì)象與一個(gè)CSocketFile對(duì)象關(guān)聯(lián),然后把CSocketFile對(duì)象與一個(gè)CArchive對(duì)象關(guān)聯(lián)。66socketCSocket

50、(&socket); CSocketFileCArchive input(&); input: CArchiveCArchive output(&); output: CArchiveCArchive與CSocket關(guān)聯(lián)67socket用archives input和output在網(wǎng)絡(luò)上串行化數(shù)據(jù)pointx=5y=5output point;CPoint point(5,5);CPoint point;pointx=5y=5pointpointx=5y=5pointx=5y=5pointx=5y=5pointx=5y=5pointx=5y=5pointx=5y=5使用CSocket傳輸C+對(duì)象68用CSocket收發(fā)數(shù)據(jù)的過程69CSocket流程70CSocket ServerCSocket sockSrvr;sockSrvr.Create(80);sockSrvr.Listen();CSocket sockRecv;so

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論