與TCP版的Echo Server類似,我們從Server Socket類中派生出Echo Server類。
class UDPEchoServer: public UDPServerSock{
public:
explicit UDPEchoServer(
unsigned short server_port,
int pre_buffer_size = 32);
~UDPEchoServer();
bool handEcho();
};
我們依然讓handEcho()返回一個bool,true表示客戶端“正常”離開(這里沒用“斷開”這個詞是因為UDP是無連接的;另外,我們這里用recvfrom()返回小于0來表示客戶端其實是“非正常”的離開了,比如連接被重置。事實上,作為UDP服務器,根本不關心客戶端是在連還是已經離開),false表示客戶端發出指令要求服務器端關閉。
UDPEchoServer::UDPEchoServer(
unsigned short server_port,
int pre_buffer_size):
UDPServerSock(server_port, pre_buffer_size)
{}
UDPEchoServer::~UDPEchoServer()
{}
bool UDPEchoServer::handEcho()
{
const std::string SHUTDOWN_CMD = "/shutdown";
while (UDPReceive() >= 0) {
std::string cmd(preBuffer, SHUTDOWN_CMD.size());
if (cmd == SHUTDOWN_CMD &&
preReceivedLength == static_cast<int>(SHUTDOWN_CMD.size())) {
return false;
}
std::cout << "Client ( "
<< inet_ntoa(lastfromSockAddr.sin_addr)
<< " : "
<< ntohs(lastfromSockAddr.sin_port)
<< " ) sent a message."
<< std::endl;
UDPSetDest(lastfromSockAddr);
UDPSendtoDest(preBuffer, preReceivedLength);
}
return true;
}
這里跟TCP有些細微的差別。在TCP中,recv()返回0表示連接正常斷開,而UDP中沒有連接和斷開的概念,recv()或者recvfrom()返回0表示收到一個0字節大小數據的數據報。另外,因為TCP是一對一連接的,所以一旦連接上,TCP服務器只能處理來自一個客戶端的echo請求(后面會講到多線程的使用,就可以讓TCP同時處理多個客戶端了);而UDP服務器則可以處理來自任何客戶端的echo請求,為了返回信息到正確的客戶端,我們的策略是,接收一個UDP數據包后,馬上刷新發送目標地址為上一次接收地址,然后再回發數據,所以這里每次多了一個重新指定發送目的地的函數。
最后,主程序基本不需要改變:
int main(int argc, char* argv[])
{
const unsigned short DEFAULT_PORT = 5000;
unsigned short server_port = DEFAULT_PORT;
if (argc == 2 && atoi(argv[1]) > 0) {
server_port = atoi(argv[1]);
}
UDPEchoServer echo_server(server_port);
bool go_on = true;
while (go_on){
go_on = echo_server.handEcho();
}
return 0;
}
本章完整源代碼下載:
Linux:
http://www.163pan.com/files/c0l000h0s.htmlwin32:
http://www.163pan.com/files/c0o000h08.html
posted on 2010-06-12 11:16
lf426 閱讀(2486)
評論(2) 編輯 收藏 引用 所屬分類:
SDL入門教程 、
socket 編程入門教程