日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MFC 网络编程 -- 总结

發布時間:2024/10/12 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MFC 网络编程 -- 总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接:http://www.cnblogs.com/lidabo/archive/2012/07/19/2598734.html

1.基于 TCP 的 socket 編程

/* 服務器端程序流程: 1.加載套接字庫 WSAStartup 2.創建套接字 socket 3.將我們創建的套接字,綁定到本機地址的某一端口上 bind 4.為套接字設置監聽模式,準備客戶請求 listen 5.等待客戶請求到來。當請求到來,將接受連接請求,并返回一個新的對應于此次連接的套接字 accept 6.用新返回的套接字和客戶端進行通信 send / recv 7.在通信結束后,關閉套接字 closesocket客戶端程序流程: 1.加載套接字庫 WSAStartup 2.創建套接字 socket 3.向服務器發出請求連接 connect 4.和服務器進行通信 send / recv 5.在通信結束后,關閉套接字 closesocket */

服務器端代碼:

#include <Winsock2.h> #include <stdio.h> #pragma comment(lib, "Ws2_32.lib") void main() { // 加載套接字庫,并進行套接字的版本協商 WORD wVersionRequested; // 指定將要加載的 winsock 庫版本 WSADATA wsaData; // 用于存儲加載的 winsock 庫版本信息 int result; // 用于檢測 WSAStartup 函數運行結果 wVersionRequested = MAKEWORD(1, 1); // 設定版本 result = WSAStartup(wVersionRequested, &wsaData); // 函數 WSAStartup 調用成功返回 0 // 出錯處理 if (result != 0) { return; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return; } // 創建套接字 SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); // 綁定套接字 SOCKADDR_IN addrInfo; // 存儲本地主機地址信息 addrInfo.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 本地主機地址 addrInfo.sin_port = htons(6000); // 端口號 addrInfo.sin_family = AF_INET; // 地址族 bind(sock, (SOCKADDR *)&addrInfo, sizeof(SOCKADDR)); // 設置套接字監聽模式 listen(sock, 5); SOCKADDR_IN addrInfoClient; // 存儲客戶端地址信息 int len = sizeof(SOCKADDR); while (true) { // 等待客戶請求到來,并返回用于通信的套接字 SOCKET sockConnect = accept(sock, (SOCKADDR *)&addrInfoClient, &len); // 下面通過剛建立的套接字,來進行通信 // 發送數據 char sendBuf[100]; sprintf(sendBuf, "這是服務器端,主機地址:%s", inet_ntoa(addrInfo.sin_addr)); send(sockConnect, sendBuf, strlen(sendBuf), 0); // 接收數據 char recvBuf[100]; recv(sockConnect, recvBuf, strlen(recvBuf), 0); // 打印接收的數據 printf("%s\n", recvBuf); closesocket(sockConnect); } }

客戶端代碼:

#include <Winsock2.h> #include <stdio.h> #pragma comment(lib,"Ws2_32.lib") void main() { // 加載套接字庫,并進行套接字的版本協商 WORD wVersionRequested; // 指定將要加載的 winsock 庫版本 WSADATA wsaData; // 用于存儲加載的 winsock 庫版本信息 int result; // 用于檢測 WSAStartup 函數運行結果 wVersionRequested = MAKEWORD(1, 1); // 設定版本 result = WSAStartup(wVersionRequested, &wsaData); // 函數 WSAStartup 調用成功返回 0 // 出錯處理 if (result != 0) { return; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return; } // 創建套接字 SOCKET sockConnect = socket(AF_INET, SOCK_STREAM, 0); // 向服務器發出連接請求 SOCKADDR_IN addrInfoServer; // 存儲服務器端地址信息 addrInfoServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrInfoServer.sin_port = htons(6000); addrInfoServer.sin_family = AF_INET; // 向服務器發出連接請求 connect(sockConnect, (SOCKADDR *)&addrInfoServer, sizeof(SOCKADDR)); // 接收數據 char recvBuf[100]; recv(sockConnect, recvBuf, sizeof(recvBuf), 0); printf("%s\n", recvBuf); // 發送數據 char sendBuf[100] = "這是客戶端\n"; send(sockConnect, sendBuf, sizeof(sendBuf) + 1, 0); //關閉套接字 closesocket(sockConnect); WSACleanup(); system("pause"); return; }

2. 基于 UDP 無連接的 socket 編程

/*服務端程序流程: 1.加載套接字庫 WSAStartup 2.創建套接字 socket 3.將創建的套接字綁定到一個本地地址和端口上 bind 4.等待接收數據。后與客戶端實現實時交流 recvfrom / sendto 5.關閉套接字 closesocket客戶端程序流程: 1.加載套接字庫 WSAStartup 2.創建套接字 socket 3.向服務器發送數據.后與服務端實現實時交流 recvfrom / sendto 4.關閉套接字 closesocket*/

服務器端代碼:

#include <Winsock2.h> #include <stdio.h> #pragma comment(lib, "Ws2_32.lib") void main() { // 加載套接字庫,并進行套接字的版本協商 WORD wVersionRequested; // 指定將要加載的 winsock 庫版本 WSADATA wsaData; // 用于存儲加載的 wdnsock 庫版本信息 int result; // 用于檢測 WSAStartup 函數運行結果 wVersionRequested = MAKEWORD(1, 1); // 設定版本 result = WSAStartup(wVersionRequested, &wsaData); // 函數 WSAStartup 調用成功返回 0 // 出錯處理 if (result != 0) { return; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return; } // 創建用于套接字 SOCKET sockConnect = socket(AF_INET, SOCK_DGRAM, 0); // 綁定套接字 SOCKADDR_IN addrInfo; // 存儲本地主機地址信息 addrInfo.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 本地主機地址 addrInfo.sin_port = htons(6000); // 端口號 addrInfo.sin_family = AF_INET; // 地址族 bind(sockConnect, (SOCKADDR *)&addrInfo, sizeof(SOCKADDR)); // 等待接收數據 char recvBuf[100]; // 接收數據緩沖 char sendBuf[100]; // 發送數據緩沖 char tempBuf[200]; SOCKADDR_IN addrInfoClient; // 存儲客戶端地址信息 int len = sizeof(SOCKADDR); while (true) { recvfrom(sockConnect, recvBuf, strlen(recvBuf), 0, (SOCKADDR *)&addrInfoClient, &len); if ('q' == recvBuf[0]) { sendto(sockConnect, "q", strlen("q") + 1, 0, (SOCKADDR *)&addrInfoClient, len); printf("聊天結束"); break; } sprintf(tempBuf, "%s 說:%s", inet_ntoa(addrInfoClient.sin_addr), recvBuf); printf("%s\n", tempBuf); // 發送數據 printf("我說:"); gets(sendBuf); sendto(sockConnect, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrInfoClient, len); } // 關閉套接字 closesocket(sockConnect); WSACleanup(); }

客戶端代碼:

#include <Winsock2.h> #include <stdio.h> #pragma comment(lib, "Ws2_32.lib") void main() { // 加載套接字庫,并進行套接字的版本協商 WORD wVersionRequested; // 指定將要加載的 winsock 庫版本 WSADATA wsaData; // 用于存儲加載的 wdnsock 庫版本信息 int result; // 用于檢測 WSAStartup 函數運行結果 wVersionRequested = MAKEWORD(1, 1); // 設定版本 result = WSAStartup(wVersionRequested, &wsaData); // 函數 WSAStartup 調用成功返回 0 // 出錯處理 if (result != 0) { return; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return; } // 創建套接字 SOCKET sockConnect = socket(AF_INET, SOCK_DGRAM, 0); // 向服務器發送數據 SOCKADDR_IN addrInfoServer; // 存儲服務器地址信息 addrInfoServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 指定服務器地址 addrInfoServer.sin_port = htons(6000); // 端口號 addrInfoServer.sin_family = AF_INET; // 地址族 int len = sizeof(SOCKADDR); char recvBuf[100]; // 接收數據緩沖 char sendBuf[100]; // 發送數據緩沖 char tempBuf[200]; while (true) { // 發送數據 printf("我說:"); gets(sendBuf); sendto(sockConnect, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrInfoServer, len); // 等待并接收數據 recvfrom(sockConnect,recvBuf, strlen(recvBuf), 0, (SOCKADDR*)&addrInfoServer, &len); if ('q' == recvBuf[0]) { sendto(sockConnect, "q", strlen("q") + 1, 0, (SOCKADDR*)&addrInfoServer, len); printf("聊天結束"); break; } sprintf(tempBuf, "%s 說:%s", inet_ntoa(addrInfoServer.sin_addr), recvBuf); printf("%s\n", tempBuf); } // 關閉套接字 closesocket(sockConnect); WSACleanup(); }

3.其他

vc網絡編程常用類型解析: 1. SOCKET 類型 SOCKET 是 socket 套接字類型,在 WINSOCK2.H 中有如下定義: typedef unsigned u_int; typedef u_int SOCKET; 可知套接字實際上就是一個無符號整形,它將被 Socket 環境管理和使用。 套接字將被創建、設置、用來發送和接收數據,最后會被關閉。 2.WORD 類型、MAKEWORD、LOBYTE、HIBYTE 宏 WORD 類型是一個 16 位的無符號整型, 在 WTYPES.H 中被定義為: typedef unsigned short WORD; 其目的是提供兩個字節的存儲, 在 Socket 中這兩個字節可以表示主版本號和副版本號。 使用 MAKEWORD 宏可以給一個 WORD 類型賦值。例如要表示主版本號 2, 副版本號 0,可以使用如下代碼: WORD wVersionRequested; wVersionRequested = MAKEWORD(2, 0); 注意低位內存存儲主版本號 2, 高位內存存儲副版本號 0,其值為 0x0002。 使用宏 LOBYTE 可以讀取 WORD 的低位字節, HIBYTE 可以讀取高位字節。 3.WSADATA 類型和 LPWSADATA 類型 WSADATA 類型是一個結構,描述了 Socket 庫的一些相關信息,其結構定義如下: typedef struct WSAData { WORD wVersion; WORD wHighVersion; char szDescription[WSADESCRIPTION_LEN + 1]; char szSystemStatus[WSASYS_STATUS_LEN + 1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR* lpVendorInfo; }WSADATA; typedef WSADATA FAR* LPWSADATA; 值得注意的是 wVersion 字段,存儲了 Socket 的版本類型。LPWSADATA 是 WSADATA 的指針類型。 他們通過 Socket 的初始化函數 WSAStartup 讀取出來。 //// vc網絡編程常用函數解析: 1. WSAStartup 函數 用于初始化 Socket 環境,函數原型: int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData); 其返回值為整型,調用方式為 PASCAL (即標準類型,PASCAL 等于__stdcall),參數有兩個, 第一個參數為 WORD 類型,指明了 Socket 的版本號,第二個參數為 LPWSADATA,指向一個用于存儲 Socket 庫信息的WSAStartup結構。 返回值: 返回值為0,則初始化成功,若不為0則為失敗。 2.WSACleanup 函數 這是 Socket 環境的退出函數,函數原型: int WSACleanup (void); 返回值: 返回值為0表示成功,SOCKET_ERROR 表示失敗。 3.socket 函數 socket 套接字的創建函數,函數原型: SOCKET socket(int af, int type, int protocol ); 第一個參數為:int af, 代表網絡地址族,目前只有一種取值有效,即 AF_INET, 代表 internet 地址族; 第二個參數為:int type, 代表網絡協議類型, SOCK_DGRAM 代表 UDP 協議, SOCK_STREAM 代表 TCP 協議。 第三個參數為:int protocol,指定網絡地址族特殊協議,目前無用,賦值0即可。 返回值: 返回值為 SOCKET, 若返回INVALID_SOCKET 則失敗。 4.bind 函數 用于將套接字綁定到一個已知地址上,函數原型: int bind(SOCKET s, const struct sockaddr FAR *name, int namelen); 第一個參數為:SOCKET s, 指定將被綁定的套接字。 第二個參數為:SOCKADDR_IN *name, 是一個sockaddr結構指針,該結構中包含了要綁定的地址和端口。 第三個參數為:int namelen, 確定第二個參數的結構長度。 返回值: 成功返回0,失敗返回SOCKET_ERROR。 /// 下面對其涉及的類型作一番解析: sockaddr 類型: sockaddr 類型是用來表示 Socket 地址的類型,同上面的 socketaddr_in 類型相比,sockaddr 的適用范圍更廣, 因為sockeaddr_in只適用于 TCP/IP 地址。sockaddr 的定義如下: struct sockaddr { ushort sa_family; char sa_data[14]; }; 可知sockaddr 的16個字節,而sockaddr_in也有16個字節,所以sockaddr_in是可以強制類型轉換為sockadddr的。 事實上也往往使用這種方法。 sockaddr_in 定義了socket發送和接收數據包的地址,其定義如下: strucr sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; 其中 in_addr 定義如下: struct in_addr { union { struct {u_char s_b1, s_b2, s_b3, s_b4} S_un_b; struct {u_short s_w1, s_w2} S_un_w; u_long S_addr; }S_un; }; 首先闡述 in_addr 的信義。 很顯然它是一個存儲 ip 地址的聯合體,有三種表達方式: 第一種用四個字節來表示IP地址的四個數字; 第二種用兩個雙字節來表示IP地址; 第三種用一個長整型來表示IP地址; 給 in_addr 賦值的一種最簡單方法是使用 inet_addr 函數, 它可以把一個代表IP地址的字符串賦值 轉換為in_addr類型。如: addrServer.sin_addr = inet_addr("192.168.0.2"); 其反函數是 inet_ntoa,可以把一個 in_addr 類型轉換為一個字符串。 sockaddr_in的含義比in_addr的含義要廣泛,其各個字段的含義和取值如下: 第一字段 short sin_family,代表網絡地址族,如前所述,只能取值AF_INET; 第二字段 u_short sin_port, 代表IP地址端口,由程序員指定; 第三字段 struct in_addr sin_addr, 代表IP地址; 第四個字段char sin_zero[8],是為了保證sockaddr_in與SOCKADDR類型的長度相等而填充進來的字段。 5.listen 函數 該函數讓一個套接字在指定IP地址的指定端口處監聽連接請求的到來,函數原型: int listen( SOCKET s, int backlog ); 該函數使得一個進程可以接受其他進程的請求,從而成為一個服務器進程。 在TCP服務器編程中listen函數把進程變為一個服務器,并指定相應的套接字變為被動連接。 listen 函數一般在調用bind之后、調用accept之前調用。 返回值: 成功則返回0,失敗返回SOCKET_ERROR,可以調用函數WSAGetLastError來取得錯誤代碼。 6.accept函數 該函數從連接請求隊列中獲得連接信息,并創建新的套接字用于收發數據,實現服務器與客戶端的通信。函數原型: SOCKET accept(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen); 第一個參數:SOCKET s, 監聽套接字 第二個參數:struct sockaddr addr, 存儲請求連接的客戶端IP地址、端口信息 第三個參數:int addrlen,第二個參數所占空間大小 返回值: 成功返回新套接字,失敗返回錯誤信息 7.connect 函數 向指定的網絡主機請求連接,函數原型: int connect(SOCKET s, const struct sockaddr FAR *name, int namelen); 第一個參數:SOCKET s, 客戶端用于收發數據的套接字。 第二個參數:struct sockaddr *name, 指定網絡主機IP地址和端口號。 第三個參數:int namelen, 第二參數長度 返回值: 成功返回0,失敗返回-1。 8.sendto、recvfrom、send、recv函數 在 Socket 中有兩套發送和接收函數。一是sendto 和recvfrom; 二是send 和 recv。 前一套在函數參數中要指明地址(UDP協議), 而后一套需要先將套接字和一個地址綁定,然后直接發送和接收,不需綁定地址。 函數原型: int sendto( SOCKET s, const char FAR *buf, int len, int flags, const struct sockaddr FAR *to, int tolen); int recvfrom(SOCKET s, char FAR* buf, int len, int flags, struct sockaddr FAR *from, int FAR *fromlen); int send(SOCKET s,const char FAR *buf, int len, int flags); int recv(SOCKET s, char FAR *buf, int len, int flags); 第一個參數: 套接字 第二個參數: 數據指針 第三個參數: 數據長度 第四個參數: 收發數據方式的標識,如果不需要特殊要求可以設置為0,其他值可參考MSDN; 第五個參數: 目標主機地址 第六個參數: 地址的長度 返回值: 運行成功則返回收發數據的字節數,失敗返回SOCKET_ERROR 9.closesocket 函數 關閉套接字,函數原型: int closesocket( SOCKET s ); 返回值: 成功返回0,失敗返回SOCKET_ERROR。

轉載于:https://www.cnblogs.com/wuyuan2011woaini/p/5740975.html

總結

以上是生活随笔為你收集整理的MFC 网络编程 -- 总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。