C++ 網(wǎng)絡(luò)編程 總結(jié)
第一次用C++寫(xiě)程序,對(duì)C++ 只是菜鳥(niǎo)級(jí)別的,倒是對(duì)C#很熟悉。兩者有很大的相似性。但也有不同。
首先寫(xiě)了一個(gè)網(wǎng)絡(luò)通訊用的小的MFC程序。發(fā)現(xiàn)
(1)MFC寫(xiě)界面真的好麻煩呀。用C#寫(xiě)的tab 分分鐘搞定的事,用C++害得我寫(xiě)了兩天.關(guān)鍵是不熟練. 還有l(wèi)ist control 控件的圖標(biāo)顯示. 真是很麻煩
不過(guò),由于最后的 detch() 函數(shù)執(zhí)行后,就真正顯示出來(lái)了.這些具體的小細(xì)節(jié),一般在 書(shū)上都沒(méi)有寫(xiě).
(2)用C++ 寫(xiě)類(lèi)的特征,基本上與C#是相似的.
說(shuō)一下網(wǎng)絡(luò)編程的問(wèn)題吧
1\一開(kāi)始并不清楚 C++ 寫(xiě)程序用的網(wǎng)絡(luò)套接字,三類(lèi)的不一樣的地方.總以為我用的VS2013,用最高級(jí)別的套接字應(yīng)該更容易一些,于是選用了CSOCKET 結(jié)果由于這個(gè)套接字是阻塞模式,結(jié)果被卡住了,卡住不知道如何做了.如果對(duì)方設(shè)備沒(méi)有反應(yīng),最不能死等吧,這樣不行.
于上網(wǎng)上搜索,發(fā)現(xiàn)一篇文章寫(xiě)到 給 CSocket 加上超時(shí).于時(shí)照抄照搬著做了一遍,可惜失敗了. 怎么查也查不出原因. 按原文章一字一句的比較,也沒(méi)有找出原因來(lái).失敗換思路
2\想到低一點(diǎn)的 CAsyncSocket 是異步操作的.這樣總可以了吧不會(huì)阻塞了吧.但是回調(diào)函數(shù)使得處理起來(lái)也不方便.在什么時(shí)候做處理,就需要消息做處理.但是也很麻煩.
3\于是,找出書(shū)來(lái),大部分書(shū)上對(duì)于網(wǎng)絡(luò)部分只是介紹了一個(gè)最基本的 Socket ,看起來(lái)也挺簡(jiǎn)單的. 就先試一下這個(gè)最基本的吧.
沒(méi)想到 30分鐘后,網(wǎng)絡(luò)程序測(cè)試成功. 而且有超時(shí)接收,超時(shí)發(fā)送,等.正合我意.
原來(lái)最基本的,才是最好的.
總結(jié)一下:
SOCKET的操作方法
以下是一個(gè)網(wǎng)絡(luò)客戶端的例子:
// client.cpp #include <iostream> #include <cstdio> #include <Winsock2.h> using namespace std; int main() { // 加載socket動(dòng)態(tài)鏈接庫(kù)(dll) WORD wVersionRequested; WSADATA wsaData; // 這結(jié)構(gòu)是用于接收Wjndows Socket的結(jié)構(gòu)信息的 int err; wVersionRequested = MAKEWORD( 1, 1 ); // 請(qǐng)求1.1版本的WinSock庫(kù) err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return -1; // 返回值為零的時(shí)候是表示成功申請(qǐng)WSAStartup } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { // 檢查這個(gè)低字節(jié)是不是1,高字節(jié)是不是1以確定是否我們所請(qǐng)求的1.1版本 // 否則的話,調(diào)用WSACleanup()清除信息,結(jié)束函數(shù) WSACleanup( ); return -1; } // 創(chuàng)建socket操作,建立流式套接字,返回套接字號(hào)sockClient // SOCKET socket(int af, int type, int protocol); // 第一個(gè)參數(shù),指定地址簇(TCP/IP只能是AF_INET,也可寫(xiě)成PF_INET) // 第二個(gè),選擇套接字的類(lèi)型(流式套接字),第三個(gè),特定地址家族相關(guān)協(xié)議(0為自動(dòng)) SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); // 將套接字sockClient與遠(yuǎn)程主機(jī)相連 // int connect( SOCKET s, const struct sockaddr* name, int namelen); // 第一個(gè)參數(shù):需要進(jìn)行連接操作的套接字 // 第二個(gè)參數(shù):設(shè)定所需要連接的地址信息 // 第三個(gè)參數(shù):地址的長(zhǎng)度 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 本地回路地址是127.0.0.1; addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); char recvBuf[100]; recv(sockClient, recvBuf, 100, 0); printf("%s\n", recvBuf); send(sockClient, "Attention: A Client has enter...\n", strlen("Attention: A Client has enter...\n")+1, 0); printf("我們可以聊五句話"); int n = 5; do{ printf("\n還剩%d次:", n); char talk[100]; printf("\nPlease enter what you want to say next(\"quit\"to exit):"); gets(talk); send(sockClient, talk, strlen(talk)+1, 0); // 發(fā)送信息 char recvBuf[100]; recv(sockClient, recvBuf, 100, 0); printf("%s Says: %s\n", "Server", recvBuf); // 接收信息 }while(--n); printf("End linking...\n"); closesocket(sockClient); WSACleanup(); // 終止對(duì)套接字庫(kù)的使用 printf("\n"); system("pause"); return 0; }
關(guān)于超時(shí)的處理方法
在send(),recv()過(guò)程中有時(shí)由于網(wǎng)絡(luò)狀況等原因,收發(fā)不能預(yù)期進(jìn)行,而設(shè)置收發(fā)超時(shí)控制:
在Linux下需要注意的是時(shí)間的控制結(jié)構(gòu)是struct timeval而并不是某一整型數(shù),
在windows下是這樣寫(xiě)的:
int nNetTimeout=1000;//1秒, //設(shè)置發(fā)送超時(shí) setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int)); //設(shè)置接收超時(shí) setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int)); 這樣做在Linux環(huán)境下是不會(huì)產(chǎn)生效果的,須如下定義: struct timeval timeout = {3,0}; //設(shè)置發(fā)送超時(shí) setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval)); //設(shè)置接收超時(shí) setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));
有兩點(diǎn)注意就是:
1)recv ()的第四個(gè)參數(shù)需為MSG_WAITALL(設(shè)置MSG_DONTWAIT可以不用阻塞在建立連接后在等等接收數(shù)據(jù)),在阻塞模式下不等到指定數(shù)目的數(shù)據(jù)不會(huì)返回,除非超時(shí)時(shí)間到。還要注意的是只要設(shè)置了接收超時(shí),在沒(méi)有MSG_WAITALL時(shí)也是有效的。說(shuō)到底超時(shí)就是不讓你的程序老在那兒等,到一定時(shí)間進(jìn)行一次返回而已。
2)即使等待超時(shí)時(shí)間值未到,但對(duì)方已經(jīng)關(guān)閉了socket, 則此時(shí)recv()會(huì)立即返回,并收到多少數(shù)據(jù)返回多少數(shù)據(jù)。
以上所述就是本文的全部?jī)?nèi)容了,希望大家能夠喜歡。
- C++?TCP網(wǎng)絡(luò)編程詳細(xì)講解
- C++?Socket實(shí)現(xiàn)TCP與UDP網(wǎng)絡(luò)編程
- 詳談C++ socket網(wǎng)絡(luò)編程實(shí)例(2)
- 詳談C++ socket網(wǎng)絡(luò)編程實(shí)例
- c++網(wǎng)絡(luò)編程下Linux的epoll技術(shù)和Windows下的IOCP模型
- C++基于socket UDP網(wǎng)絡(luò)編程實(shí)現(xiàn)簡(jiǎn)單聊天室功能
- C++中Socket網(wǎng)絡(luò)編程實(shí)例詳解
- C++網(wǎng)絡(luò)編程詳細(xì)講解
相關(guān)文章
VSCode遠(yuǎn)程開(kāi)發(fā)調(diào)試服務(wù)器c/c++代碼
語(yǔ)音相關(guān)的好多項(xiàng)目要在linux上跑,但代碼開(kāi)發(fā)大多是在PC機(jī)上,本篇簡(jiǎn)單介紹一下怎么在個(gè)人電腦上用VSCode遠(yuǎn)程開(kāi)發(fā)調(diào)試服務(wù)器上的c/c++代碼。感興趣的朋友跟隨小編一起看看吧2020-04-04C++中關(guān)于多態(tài)實(shí)現(xiàn)和使用方法
這篇文章主要介紹了C++中關(guān)于多態(tài)實(shí)現(xiàn)和使用方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07Qt Design Studio創(chuàng)建工程的實(shí)現(xiàn)方法
Qt Design Studio它允許設(shè)計(jì)人員和開(kāi)發(fā)人員使用通用的設(shè)計(jì)、開(kāi)發(fā)、分析和調(diào)試工具在不同的開(kāi)發(fā)平臺(tái)上共享一個(gè)項(xiàng)目,本文主要介紹了Qt Design Studio創(chuàng)建工程的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的可以了解一下2022-05-05C++ 數(shù)據(jù)結(jié)構(gòu) 堆排序的實(shí)現(xiàn)
這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu) 堆排序的實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-06-06C語(yǔ)言新手練習(xí)題之求第n個(gè)斐波那契數(shù)
斐波那契數(shù)列這一個(gè)大一上C語(yǔ)言就有的問(wèn)題大家應(yīng)該都不陌生,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言新手練習(xí)題之求第n個(gè)斐波那契數(shù)的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11C++結(jié)構(gòu)體數(shù)組實(shí)現(xiàn)貪吃蛇
這篇文章主要為大家詳細(xì)介紹了C++結(jié)構(gòu)體數(shù)組實(shí)現(xiàn)貪吃蛇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03