|
Posted on 2009-10-20 17:07 lantionzy 閱讀(2579) 評(píng)論(12) 編輯 收藏 引用 所屬分類(lèi): C++ Primer 、 VC/MFC
對(duì)于聊天程序來(lái)說(shuō),即使丟失一些數(shù)據(jù),也不會(huì)影響信息的交流,可以根據(jù)上下文的情況,知道對(duì)方所要表達(dá)的意思,或者根據(jù)對(duì)方的信息,重新發(fā)送我們所說(shuō)的話。對(duì)于TCP來(lái)說(shuō),在通信前,需要經(jīng)過(guò)三步握手協(xié)議以建立連接,而建立過(guò)程往往是比較消耗時(shí)間的。建立連接后,在聊天過(guò)程中,可能經(jīng)過(guò)好長(zhǎng)一段時(shí)間,雙方才會(huì)說(shuō)一句話,那么連接應(yīng)該保持還是應(yīng)先斷開(kāi),等對(duì)方說(shuō)話時(shí)再建立呢?也就是說(shuō),TCP協(xié)議的面向連接、數(shù)據(jù)確認(rèn)和重傳機(jī)制將會(huì)影響聊天的效率。所以對(duì)于聊天類(lèi)的軟件來(lái)說(shuō),通常都采用基于UDP的方式來(lái)實(shí)現(xiàn)。其特點(diǎn)就是不需要建立連接,也沒(méi)有數(shù)據(jù)確認(rèn)和重傳機(jī)制,因此適時(shí)性較高。 本示例的基本實(shí)現(xiàn)過(guò)程是:客戶端通過(guò)鍵盤(pán)輸入數(shù)據(jù),數(shù)據(jù)被發(fā)送到服務(wù)器。后者接收到數(shù)據(jù)后,需要進(jìn)行判斷,如果發(fā)來(lái)的數(shù)據(jù)串為“quit”,表明對(duì)方向退出聊天過(guò)程,于是服務(wù)器端也發(fā)送字符串“quit”,聊天過(guò)程終止;否則將接收到的信息和對(duì)方的IP地址進(jìn)行格式化后,在屏幕上輸出。同樣在客戶端也需要進(jìn)行相應(yīng)的判斷和輸出。 首先編寫(xiě)服務(wù)器端程序,實(shí)現(xiàn)代碼如下:
 Chat Server
#pragma comment(lib,"ws2_32.lib")
#include <WINSOCK2.H>
#include <stdio.h>

void main()
  {
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1,1);
err = WSAStartup(wVersionRequested, &wsaData);
if( err != 0)
 {
return;
}
if(LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1)
 {
WSACleanup();
return;
}
SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
char recvBuf[100];
char sendBuf[100];
char tempBuf[200];
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
while(1)
 {
recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&addrClient, &len);
if(!strcmp("quit", recvBuf))
 {
sendto(sockSrv, "quit", strlen("quit") + 1, 0, (SOCKADDR*)&addrClient, len);
printf("Chat end!\n");
break;
}
sprintf(tempBuf, "%s say:%s\n", inet_ntoa(addrClient.sin_addr),recvBuf);
printf("%s\n",tempBuf);
printf("Please input data:\n");
gets(sendBuf);
sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrClient, len);
}
closesocket(sockSrv);
WSACleanup();
}
下面編寫(xiě)聊天客戶端程序,實(shí)現(xiàn)代碼如:
 Chat Client
#pragma comment(lib,"ws2_32.lib")
#include <WINSOCK2.H>
#include <stdio.h>

void main()
  {
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1,1);
err = WSAStartup(wVersionRequested, &wsaData);
if( err != 0)
 {
return;
}
if(LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1)
 {
WSACleanup();
return;
}
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
char recvBuf[100];
char sendBuf[100];
char tempBuf[200];
int len = sizeof(SOCKADDR);
while(1)
 {
printf("Please input data:\n");
gets(sendBuf);
sendto(sockClient, sendBuf,strlen(sendBuf)+1, 0, (SOCKADDR*)&addrSrv, len);
recvfrom(sockClient, recvBuf, 100, 0, (SOCKADDR*)&addrSrv, &len);
if(!strcmp("quit", recvBuf))
 {
sendto(sockClient, "quit", strlen("quit") + 1, 0, (SOCKADDR*)&addrSrv, len);
printf("Chat end!\n");
break;
}
sprintf(tempBuf, "%s say:%s\n", inet_ntoa(addrSrv.sin_addr), recvBuf);
printf("%s\n", tempBuf);
}
closesocket(sockClient);
WSACleanup();
}
這樣我們就實(shí)現(xiàn)了一個(gè)非常簡(jiǎn)單的基于UDP的網(wǎng)絡(luò)聊天程序。 剖析網(wǎng)絡(luò)編程(1)-- 基于TCP的的網(wǎng)絡(luò)應(yīng)用程序剖析網(wǎng)絡(luò)編程(2)-- 基于UDP的的網(wǎng)絡(luò)應(yīng)用程序剖析網(wǎng)絡(luò)編程(3)-- 基于TCP/UDP網(wǎng)絡(luò)編程應(yīng)注意的幾個(gè)地方轉(zhuǎn)到博客首頁(yè)查看更多隨筆
Feedback
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-20 19:45 by
給樓主提個(gè)建議: 這樣的文章可能對(duì)寫(xiě)作者來(lái)說(shuō)意義和樂(lè)趣都很大, 但是作為一個(gè)讀者, 我實(shí)在感覺(jué)不出來(lái)"閱讀的快感".
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-21 09:15 by
@欲三更
既然對(duì)寫(xiě)作者來(lái)說(shuō)意義和樂(lè)趣都很大,已經(jīng)很不錯(cuò)了。不同的文章適合不同的人看,也許對(duì)有些讀者來(lái)說(shuō)這個(gè)是有用的。能寫(xiě)出來(lái)就不是壞事,哪個(gè)牛人不是一步步走過(guò)來(lái)的?
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-21 09:18 by
@幽靈
牛人是一步一步走過(guò)來(lái)的,說(shuō)的好啊,可惜我還是個(gè)菜鳥(niǎo),剛起步,還在一步一步的走,什么時(shí)候能是個(gè)牛人呢............
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-21 09:40 by
@欲三更
這位大哥,你一定是個(gè)牛人,我的文章水平太低,以后多向你學(xué)習(xí)。
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-21 09:41 by
@俠客西風(fēng)
我也是個(gè)菜鳥(niǎo),也正在一步步走。慢慢積累吧,網(wǎng)上牛人多,資源也多,加油!
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-22 20:17 by
blog是什么意思? 就是為了讓別人有“閱讀的快感”的? 拿這個(gè)來(lái)說(shuō)事,簡(jiǎn)直本末倒置。
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-26 11:25 by
以前也做過(guò)一個(gè)TCP+UDP帶注冊(cè)登錄,在線用戶實(shí)時(shí)更新,消息,文件傳送的CMD程序,所有一切都是命令,好懷念啊
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-26 15:07 by
本來(lái)是來(lái)看文章的。 看到大家說(shuō)這個(gè)問(wèn)題,我也說(shuō)兩句。既然寫(xiě)成Blog發(fā)表出來(lái),就是share啦。既然要share 為什么不寫(xiě)的更可讀呢。
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-26 15:11 by
看了一遍 覺(jué)得LZ的程序真的不太需要解釋了。
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2009-10-28 14:19 by
樓主文章,收藏了
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2011-01-11 08:05 by
好吧,我承認(rèn)我受益匪淺
# re: 剖析網(wǎng)絡(luò)編程(4)-- 基于UDP的簡(jiǎn)單聊天程序 回復(fù) 更多評(píng)論
2015-12-07 12:58 by
@欲三更 尼瑪,這不是孫鑫的那本書(shū)上的內(nèi)容嗎,不過(guò)我也才看到,正在測(cè)試
|