随笔 - 96  文章 - 255  trackbacks - 0
<2010年6月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

E-mail:zbln426@163.com QQ:85132383 长期寻找对战略游戏感兴趣的合作伙伴。

常用链接

留言簿(21)

随笔分类

随笔档案

SDL相关网站

我的个人网页

我的小游戏

资源下载

搜索

  •  

积分与排名

  • 积分 - 485013
  • 排名 - 37

最新评论

阅读排行榜

评论排行榜

//Filename: SockClass.hpp

#ifndef SOCK_CLASS_HPP
#define SOCK_CLASS_HPP

#include 
<iostream>
#include 
<winsock2.h>

namespace sockClass
{
void error_info(const char* s);
}

class WinsockAPI{
private:
    WSADATA wsaData;
public:
    WinsockAPI(
int low_byte = 2int high_byte = 2);
    
~WinsockAPI();
    
void showVersion() const;
};

class BaseSock{
protected:
    
int sockFD;
public:
    BaseSock();
    
virtual ~BaseSock() = 0;
    
const int& showSockFD() const;
};

class TCPListenSock: public BaseSock{
private:
    sockaddr_in listenSockAddr;
public:
    TCPListenSock(unsigned 
short listen_port);
    
~TCPListenSock();
    
void TCPListen(
        
int max_connection_requests = 10const;
};

class TCPServerSock: public BaseSock{
private:
    sockaddr_in clientSockAddr;
protected:
    
char* preBuffer;
    
int preBufferSize;
    mutable 
int preReceivedLength;
public:
    TCPServerSock(
        
const TCPListenSock& listen_sock,
        
int pre_buffer_size = 32);
    
virtual ~TCPServerSock();
    
int TCPReceive() const;
    
int TCPSend(const char* send_data,
            
const int& data_length) const;
};

#endif //SockClass.hpp

//Filename: SockClass.cpp

#include 
"SockClass.hpp"

//sockClass

namespace sockClass
{
void error_info(const char* s)
{
    std::cerr 
<< s << std::endl;
    
throw WSAGetLastError();
}
}

//class WinsockAPI

WinsockAPI::WinsockAPI(
int low_byte, int high_byte)
{
    
const WORD wVersionRequested = MAKEWORD(low_byte, high_byte);
    
int wsa_startup_err = WSAStartup(wVersionRequested, &wsaData);
    
if (wsa_startup_err != 0) {
        std::cerr 
<< "WSAStartup() failed." << std::endl;
        
throw wsa_startup_err;
    }
}

WinsockAPI::
~WinsockAPI()
{
    WSACleanup();
}

void WinsockAPI::showVersion() const
{
    std::cout    
<< "The version of Winsock.dll is " 
                
<< int(LOBYTE(wsaData.wVersion)) 
                
<< "." 
                
<< int(HIBYTE(wsaData.wVersion)) 
                
<< "." 
                
<< std::endl;
    
return;
}

//class BaseSock

BaseSock::BaseSock():
sockFD(
-1)
{}

BaseSock::
~BaseSock()
{}

const int& BaseSock::showSockFD() const
{
    
return sockFD;
}

//class TCPListenSock

TCPListenSock::TCPListenSock(unsigned 
short listen_port)
{
    sockFD 
= socket(PF_INET,
                    SOCK_STREAM,
                    IPPROTO_TCP);
    
if (sockFD < 0) {
        sockClass::error_info(
"socket() failed.");
    }
    memset(
&listenSockAddr, 0sizeof(listenSockAddr));
    listenSockAddr.sin_family 
= AF_INET;
    listenSockAddr.sin_addr.s_addr 
= htonl(INADDR_ANY);
    listenSockAddr.sin_port 
= htons(listen_port);
    
if (bind(    sockFD,
                (sockaddr
*)&listenSockAddr,
                
sizeof(listenSockAddr)) < 0) {
        sockClass::error_info(
"bind() failed.");
    }
}

TCPListenSock::
~TCPListenSock()
{
    closesocket(sockFD);
}

void TCPListenSock::TCPListen(
                        
int max_connection_requests) const
{
    
if (listen(    sockFD,
                max_connection_requests) 
< 0) {
        sockClass::error_info(
"listen() failed.");
    }
}

//class TCPServerSock

TCPServerSock::TCPServerSock(
                
const TCPListenSock& listen_sock,
                
int pre_buffer_size):
preBufferSize(pre_buffer_size),
preReceivedLength(
0)
{
    preBuffer 
= new char[preBufferSize];

    
int clientSockAddrLen = sizeof(clientSockAddr);
    sockFD 
= accept(    listen_sock.showSockFD(),
                        (sockaddr
*)&clientSockAddr,
                        
&clientSockAddrLen);
    
if (sockFD < 0) {
        sockClass::error_info(
"accept() failed.");
    }
    std::cout    
<< "Client (IP: "
                
<< inet_ntoa(clientSockAddr.sin_addr)
                
<< ") conneted." << std::endl;
}

TCPServerSock::
~TCPServerSock()
{
    delete [] preBuffer;
    closesocket(sockFD);
}

int TCPServerSock::TCPReceive() const
{
    preReceivedLength 
= recv(    sockFD,
                                preBuffer,
                                preBufferSize,
                                
0);
    
if (preReceivedLength < 0) {
        sockClass::error_info(
"recv() failed.");
    } 
else if (preReceivedLength == 0) {
        std::cout 
<< "Client has been disconnected.\n";
        
return 0;
    }
    
return preReceivedLength;
}

int TCPServerSock::TCPSend(const char* send_data,
                           
const int& data_length) const
{
    
if (data_length > preBufferSize) {
        
throw "Data is too large, resize preBufferSize.";
    }

    
int sent_length = send(    sockFD,
                            send_data,
                            data_length,
                            
0);
    
if (sent_length < 0) {
        sockClass::error_info(
"send() failed.");
    } 
else if (sent_length != data_length) {
        sockClass::error_info(
"sent unexpected number of bytes.");
    }

    
return sent_length;
}

//Filename AppSock.hpp

#ifndef APP_SOCK_HPP
#define APP_SOCK_HPP

#include 
"SockClass.hpp"

class TCPEchoServer: public TCPServerSock{
public:
    TCPEchoServer(
        
const TCPListenSock& listen_sock,
        
int pre_buffer_size = 32);
    
~TCPEchoServer();
    
bool handEcho() const;
};

#endif //AppSock.hpp

//Filename: AppSock.cpp

#include 
<string>
#include 
"AppSock.hpp"

TCPEchoServer::TCPEchoServer(
const TCPListenSock& listen_sock, int pre_buffer_size):
TCPServerSock(listen_sock, pre_buffer_size)
{}

TCPEchoServer::
~TCPEchoServer()
{}

bool TCPEchoServer::handEcho() const
{
    
const std::string SHUTDOWN_CMD = "/shutdown";
    
while (TCPReceive() > 0) {
        std::
string cmd(preBuffer, SHUTDOWN_CMD.size());
        
if (cmd == SHUTDOWN_CMD && preReceivedLength == SHUTDOWN_CMD.size()) {
            
return false;
        }
        TCPSend(preBuffer, preReceivedLength);
    }
    
return true;
}

//Filename: main.cpp

#include 
"SockClass.hpp"
#include 
"AppSock.hpp"

int TCP_echo_server(int argc, char* argv[]);

int main(int argc, char* argv[])
{
    
int mainRtn = 0;
    
try {
        mainRtn 
=TCP_echo_server(argc, argv);
    }
    
catch (const char* s) {
        perror(s);
        
return 1;
    }
    
catch (const int& err) {
        std::cerr 
<< "Error: " << err << std::endl;
        
return 1;
    }

    
return mainRtn;
}

int TCP_echo_server(int argc, char* argv[])
{
    
const unsigned short DEFAULT_PORT = 5000;
    unsigned 
short listen_port = DEFAULT_PORT;
    
if (argc == 2 && atoi(argv[1]) > 0) {
        listen_port 
= atoi(argv[1]);
    }

    WinsockAPI winsockInfo;
    winsockInfo.showVersion();

    TCPListenSock listen_sock(listen_port);
    listen_sock.TCPListen();

    
bool go_on = true;
    
while (go_on){
        TCPEchoServer echo_server(listen_sock);
        go_on 
= echo_server.handEcho();
    }

    
return 0;
}
posted on 2010-06-03 10:45 lf426 阅读(1865) 评论(2)  编辑 收藏 引用 所属分类: SDL入门教程socket 编程入门教程

FeedBack:
# re: socket 编程入门教程(二)winsock演示程序:TCP Server 2010-10-16 21:21 莉萨
为什么要有一个TCPEchoServerSock类呢.

ListenSock和TCPServerSock就能完成任务了阿,从职责上说,EchoServer只是多了个发送指令的任务,不应该继承EchoServer吧.

用一个独立Echo类,引用一个const TCPServerSock对象,是不是更妥当呢?

入门教程(2)没有入门教程(1)那么耐心仔细了呢...楼主加油.  回复  更多评论
  
# re: socket 编程入门教程(二)winsock演示程序:TCP Server 2010-10-16 21:21 莉萨
我上面第二句说错了,EchoServer不应该继承ServerSock  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理