剖析網絡編程(4)-- 基于UDP的簡單聊天程序
Posted on 2009-10-20 17:07 lantionzy 閱讀(2613) 評論(12) 編輯 收藏 引用 所屬分類: C++ Primer 、VC/MFC 對于聊天程序來說,即使丟失一些數據,也不會影響信息的交流,可以根據上下文的情況,知道對方所要表達的意思,或者根據對方的信息,重新發送我們所說的話。對于TCP來說,在通信前,需要經過三步握手協議以建立連接,而建立過程往往是比較消耗時間的。建立連接后,在聊天過程中,可能經過好長一段時間,雙方才會說一句話,那么連接應該保持還是應先斷開,等對方說話時再建立呢?也就是說,TCP協議的面向連接、數據確認和重傳機制將會影響聊天的效率。所以對于聊天類的軟件來說,通常都采用基于UDP的方式來實現。其特點就是不需要建立連接,也沒有數據確認和重傳機制,因此適時性較高。
本示例的基本實現過程是:客戶端通過鍵盤輸入數據,數據被發送到服務器。后者接收到數據后,需要進行判斷,如果發來的數據串為“quit”,表明對方向退出聊天過程,于是服務器端也發送字符串“quit”,聊天過程終止;否則將接收到的信息和對方的IP地址進行格式化后,在屏幕上輸出。同樣在客戶端也需要進行相應的判斷和輸出。
首先編寫服務器端程序,實現代碼如下:

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();
}
下面編寫聊天客戶端程序,實現代碼如:

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();
}
這樣我們就實現了一個非常簡單的基于UDP的網絡聊天程序。
剖析網絡編程(1)-- 基于TCP的的網絡應用程序
剖析網絡編程(2)-- 基于UDP的的網絡應用程序
剖析網絡編程(3)-- 基于TCP/UDP網絡編程應注意的幾個地方
轉到博客首頁查看更多隨筆
本示例的基本實現過程是:客戶端通過鍵盤輸入數據,數據被發送到服務器。后者接收到數據后,需要進行判斷,如果發來的數據串為“quit”,表明對方向退出聊天過程,于是服務器端也發送字符串“quit”,聊天過程終止;否則將接收到的信息和對方的IP地址進行格式化后,在屏幕上輸出。同樣在客戶端也需要進行相應的判斷和輸出。
首先編寫服務器端程序,實現代碼如下:































































下面編寫聊天客戶端程序,實現代碼如:




























































這樣我們就實現了一個非常簡單的基于UDP的網絡聊天程序。
剖析網絡編程(1)-- 基于TCP的的網絡應用程序
剖析網絡編程(2)-- 基于UDP的的網絡應用程序
剖析網絡編程(3)-- 基于TCP/UDP網絡編程應注意的幾個地方
轉到博客首頁查看更多隨筆