posts - 225, comments - 62, trackbacks - 0, articles - 0
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
//SocketLib.h,这是一个已发现BUG的版本
#include <assert.h>
//Code Block 2.1 头文件包含
#ifdef WIN32
    #include 
"winsock2.h"
    #include 
"Ws2tcpip.h"
#else
    #include 
<sys/types.h>
    #include 
<sys/socket.h>
    #include 
<netinet/in.h>
    #include 
<unistd.h>
    #include 
<netdb.h>
    #include 
<arpa/inet.h>
#endif
//End Code Block 2.1

//Code Block 2.2 为交互兼容性进行重新定义和全局化处理
#ifdef WIN32
    WSADATA g_wsadata;
    
#define CloseSocket closesocket
    
#define GetSocketError WSAGetLastError
    
#define StartSocketLib WSAStartup( MAKEWORD(2,2) , &g_wsadata);
    
#define CloseSocketLib WSACleanup();
    #ifndef socklen_t
        typedef 
int socklen_t;
    
#endif
#else
    
#define CloseSocket close
    
#define GetSocketError errno
    
#define StartSocketLib {}
    
#define CloseSocketLib {}
#endif
//End Code Block 2.2

class BaseSocket{
protected:
    
int m_sock;
    
bool m_closed;
    
bool m_err;
    
static int s_cnt;
public:
    /*当BaseSocket的某个子类的实例在函数调用中以值方式传递,则s_cnt没有自增,但析构时s_cnt会自减
    更严重的是,形参或返回值销毁时会使套接字失效*/
    BaseSocket(){
        
if(s_cnt++ == 0){
            StartSocketLib;
        }
        m_closed
=false;
        m_err
=false;
        m_sock
=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    }
    
~BaseSocket(){
        
if(!isClosed()){
            close();
        }
        
if(--s_cnt == 0){
            CloseSocketLib;
        }
    }
    
void close(){
        shutdown(m_sock,
2);
        CloseSocket(m_sock);
        m_closed
=true;
    }
    
bool isClosed(){
        
return m_closed;
    }
    
operator bool (){
        
return !m_err;
    }
};

int BaseSocket::s_cnt;

class Socket: public BaseSocket{
public:
    Socket(){}

    Socket(
int sock){
        m_sock
=sock;
    }

    Socket(
char* ipaddr,unsigned short port){
        
int err=connect(ipaddr,port);
        
if(err!=0)assert(!"Connect Failed!");
    }

    
int connect(char* ipaddr,unsigned short port){
        sockaddr_in socketaddress;
        socketaddress.sin_family
=AF_INET;
        socketaddress.sin_port
=htons(port);
        socketaddress.sin_addr.s_addr
=inet_addr(ipaddr);
        memset(
&(socketaddress.sin_zero),0,8);
        
return ::connect(m_sock,(sockaddr*)&socketaddress,sizeof(sockaddr_in));
    }

    
int send(const char* data,int size){
        
return ::send(m_sock,data,size,0);
    }

    Socket
& operator << (const char* str){
        send(str,strlen(str)
+1);
        
return *this;
    }

    
char* recv(){
        
static char buf[1024];
        
int err=::recv(m_sock,buf,1024,0);
        
if(err<=0)m_err=true;
        
return buf;
    }

    Socket
& operator >> (char* str){
        strcpy(str,recv());
        
return *this;
    }
};

class ServerSocket: public BaseSocket{
    sockaddr_in m_socketaddress;
public:
    ServerSocket(){}

    ServerSocket(unsigned 
short port,int backlog=50,unsigned long ipaddr=INADDR_ANY){
        
int err;
        err
=bind(port,ipaddr);
        
if(err!=0)assert(!"Bind Failed!");
        err
=listen(backlog);
        
if(err!=0)assert(!"Listen Failed!");
    }

    
int bind(unsigned short port,unsigned long ipaddr=INADDR_ANY){
        m_socketaddress.sin_family
=AF_INET;
        m_socketaddress.sin_port
=htons(port);
        m_socketaddress.sin_addr.s_addr
=htonl(ipaddr);
        memset(
&(m_socketaddress.sin_zero),0,8);
        
return ::bind(m_sock,(sockaddr*)&m_socketaddress,sizeof(sockaddr_in));
    }

    
int listen(int backlog=50){
        
return ::listen(m_sock,backlog);
    }

    Socket accept(){
        
int dsock;
        
int sa_size=sizeof(sockaddr_in);
        dsock
=::accept(m_sock,(sockaddr*)&m_socketaddress,&sa_size);
        Socket s
=Socket(dsock);
        
return s;
    }
};

//SocketLib.h
//version 2
//最后修改时间:2009-02-03 22:09
#include <assert.h>
//Code Block 2.1 头文件包含
#ifdef WIN32
    #include 
"winsock2.h"
    #include 
"Ws2tcpip.h"
#else
    #include 
<sys/types.h>
    #include 
<sys/socket.h>
    #include 
<netinet/in.h>
    #include 
<unistd.h>
    #include 
<netdb.h>
    #include 
<arpa/inet.h>
#endif
//End Code Block 2.1

//Code Block 2.2 为交互兼容性进行重新定义和全局化处理
#ifdef WIN32
    WSADATA g_wsadata;
    
#define CloseSocket closesocket
    
#define GetSocketError WSAGetLastError
    
#define StartSocketLib WSAStartup( MAKEWORD(2,2) , &g_wsadata);
    
#define CloseSocketLib WSACleanup();
    #ifndef socklen_t
        typedef 
int socklen_t;
    
#endif
#else
    
#define CloseSocket close
    
#define GetSocketError errno
    
#define StartSocketLib {}
    
#define CloseSocketLib {}
#endif
//End Code Block 2.2

namespace SocketLib{
class System{
public:
    System(){
        StartSocketLib;
    }
    
~System(){
        CloseSocketLib;
    }
}system;
};

class BaseSocket{
protected:
    
int m_sock;
    
bool m_closed;
    
bool m_err;
public:
    BaseSocket(){
        m_closed
=false;
        m_err
=false;
        m_sock
=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    }

    
void close(){
        shutdown(m_sock,
2);
        CloseSocket(m_sock);
        m_closed
=true;
    }

    
bool isClosed(){
        
return m_closed;
    }

    
operator bool (){
        
return !m_err;
    }

    
int getSock(){
        
return m_sock;
    }

};

class Socket: public BaseSocket{
public:
    Socket(){}

    Socket(
int sock){
        m_sock
=sock;
    }

    Socket(
char* ipaddr,unsigned short port){
        
int err=connect(ipaddr,port);
        
if(err!=0)assert(!"Connect Failed!");
    }

    
int connect(char* ipaddr,unsigned short port){
        sockaddr_in socketaddress;
        socketaddress.sin_family
=AF_INET;
        socketaddress.sin_port
=htons(port);
        socketaddress.sin_addr.s_addr
=inet_addr(ipaddr);
        memset(
&(socketaddress.sin_zero),0,8);
        
return ::connect(m_sock,(sockaddr*)&socketaddress,sizeof(sockaddr_in));
    }

    
int send(const char* data,int size){
        
return ::send(m_sock,data,size,0);
    }

    Socket
& operator << (const char* str){
        send(str,strlen(str)
+1);
        
return *this;
    }

    
char* recv(){
        
static char buf[1024];
        
int err=::recv(m_sock,buf,1024,0);
        
if(err<=0)m_err=true;
        
return buf;
    }

    Socket
& operator >> (char* str){
        strcpy(str,recv());
        
return *this;
    }
};


class ServerSocket: public BaseSocket{
    sockaddr_in m_socketaddress;
public:
    ServerSocket(){}

    ServerSocket(unsigned 
short port,int backlog=50,unsigned long ipaddr=INADDR_ANY){
        
int err;
        err
=bind(port,ipaddr);
        
if(err!=0)assert(!"Bind Failed!");
        err
=listen(backlog);
        
if(err!=0)assert(!"Listen Failed!");
    }

    
int bind(unsigned short port,unsigned long ipaddr=INADDR_ANY){
        m_socketaddress.sin_family
=AF_INET;
        m_socketaddress.sin_port
=htons(port);
        m_socketaddress.sin_addr.s_addr
=htonl(ipaddr);
        memset(
&(m_socketaddress.sin_zero),0,8);
        
return ::bind(m_sock,(sockaddr*)&m_socketaddress,sizeof(sockaddr_in));
    }

    
int listen(int backlog=50){
        
return ::listen(m_sock,backlog);
    }

    Socket accept(){

        
int dsock;
        
int sa_size=sizeof(sockaddr_in);
        dsock
=::accept(m_sock,(sockaddr*)&m_socketaddress,&sa_size);
        Socket s
=Socket(dsock);
        
return s;
    }
};

//服务器端测试程序
#include <iostream>
#include 
"SocketLib.h"
using namespace std;

char buf[1024];

int main()
{
    ServerSocket lsock
=ServerSocket(4000);
    cout
<<"Listening Port 4000"<<endl;
    
    Socket dsock
=lsock.accept();
    cout
<<"Connection Established"<<endl;
    
    lsock.close();
    
//cout<<"Stop Listening"<<endl;
    
    
while(dsock>>buf){
        cout
<<buf<<endl;
    }
    
    dsock.close();
    cout
<<"Connection Closed"<<endl;
}

//客户端测试程序
#include <iostream>
#include 
"SocketLib.h"

using namespace std;

char buf[1024];

int main()
{
    Socket s(
"127.0.0.1",4000);
    
while(cin>>buf){
        s
<<buf;
    }
}

修改版改变了调用StartSocketLib和CloseSocketLib的方法,通过定义全局对象,在构造和析构函数中执行。
只有注册用户登录后才能发表评论。