对Windows和Linux的Socket进一步封装

作者在 2010-07-04 03:15:29 发布以下内容

   呵呵,昨天对Windows下的Socket API进行了简单的封装,今天趁热打铁把Linux下的Socket也一起封装了到了一个类中,相比昨天的那个类,只是做了少些修改,增加了一些宏,废话 不多说了,看下面代码,(顺便带上一个简单的聊天代码Linux和Windows对聊的)。如果用C++的异常对出错进行处理就更好了,呵呵,有时间在添 加上^_^


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __SOCKET_H__
#define __SOCKET_H__

#define __WINDOWS__

#include <string>
using namespace std;

#if defined (__WINDOWS__)
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
typedef int   socklen;

#elif defined(__LINUX__)

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>
typedef int    SOCKET;
typedef socklen_t socklen;
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close

#endif

typedef struct sockaddr   SOCKADDR;
typedef struct sockaddr_in SOCKADDR_IN;

struct Host
{
    string ip;
    int port;
};

class Socket
{
public:
    enum Type {TCP = SOCK_STREAM, UDP = SOCK_DGRAM};
public:
    Socket(int type = SOCK_STREAM, int af = AF_INET, int protocol = 0);
    Socket(const char *ip, int port,int type = SOCK_STREAM,int af = AF_INET, int protocol = 0);
    Socket(const string &ip, int port, int type = SOCK_STREAM,int af = AF_INET, int protocol = 0);
    Socket& operator=(const Socket &other);
    virtual ~Socket();
    static int InitSocket(int x = 2, int y = 2, WSADATA *wsa = NULL);
    static int ClearSocket();
public:
    int Create(int type = SOCK_STREAM,int af = AF_INET,int protocol = 0);      //creat socket
    int Bind(int port);
    int Listen(int backlog = 5);
    Socket Accept(void);
    Socket* Accept(Socket *socket);
    // try connect to remote host
    int Connect(const char *ip, int port);
    int Connect(const string &ip, int port);
    int Connect();
    // close previous connection and connect to another socket
    int Reconnect(const char *ip, int port);
    // send data to peer
    int Send(const char* buf, int len = -1, int flags = 0);
    int Send(const string &buf,int flags = 0);
    int Receive(char* buf, int len, int flags = 0);
    //UDP
    int SendTo(char *ip, int port,const char* buf, int len = -1, int flags = 0);
    int SendTo(char *ip, int port,const string &str,int flags = 0);
    int ReceiveFrom(char *buf, int len, Host *host = NULL, int flags = 0);
    // close connection
    int Close(void);

public:
    char* GetIP() const
    {
        return inet_ntoa(m_remoteaddr.sin_addr);
    }
    int GetPort() const
    {
        return m_remoteaddr.sin_port;
    }
    int GetBindPort() const
    {
        return this->m_bindPort;
    }
    SOCKET GetSocket() const
    {
        return this->m_SocketId;
    }
  
protected:
    string m_ip;                        //Remote Host IP
    int m_port;                         //Remote Host port
    int m_bindPort;                     //bind on local port
    SOCKET m_SocketId;
    SOCKADDR_IN m_remoteaddr;           //Remote Host address info
};

#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "Socket.h"
#include <assert.h>

int Socket::InitSocket(int x, int y, WSADATA *wsa)
{
#if defined (__WINDOWS__)
    WSADATA wsaData;
    return WSAStartup(MAKEWORD(x,y), ( NULL == wsa ) ? &wsaData : wsa);
#elif defined(__LINUX__)
    return 1;
#endif
}

int Socket::ClearSocket()
{
#if defined (__WINDOWS__)
    return WSACleanup();
#elif defined(__LINUX__)
    return 1;
#endif
}

Socket::Socket(int type, int af, int protocol)
{
    this->m_bindPort = 0;
    this->m_port = 0;
    this->m_SocketId = INVALID_SOCKET;
    this->Create(type,af,protocol);
    memset(&this->m_remoteaddr,0,sizeof(SOCKADDR_IN));
}

Socket& Socket::operator =(const Socket &other)
{
    if( this != &other )
    {
        this->m_bindPort = other.m_bindPort;
        this->m_ip = other.m_ip;
        this->m_port = other.m_port;
        this->m_SocketId = other.m_SocketId;
        memcpy(&this->m_remoteaddr,&other.m_remoteaddr,sizeof(SOCKADDR_IN));
    }
    return *this;
}

Socket::Socket(const char *ip, int port,int type,int af, int protocol)
{
    this->m_bindPort = 0;
    this->m_port = port;
    this->m_ip = ip;
    this->m_SocketId = INVALID_SOCKET;
    this->Create(type,af,protocol);
    memset(&this->m_remoteaddr,0,sizeof(SOCKADDR_IN));
    m_remoteaddr.sin_family = AF_INET;
    m_remoteaddr.sin_port = htons(port);
    m_remoteaddr.sin_addr.s_addr = inet_addr(ip);
}

Socket::Socket(const string &ip, int port,int type,int af, int protocol)
{
    Socket(ip.c_str(),port,type,af,protocol);
}


Socket::~Socket()
{
    this->Close();
}

int Socket::Create(int type, int af, int protocol)
{
    if( INVALID_SOCKET != this->m_SocketId )
    {
        this->Close();
    }
    return (this->m_SocketId = socket(af,type,protocol)) == INVALID_SOCKET ;
}

int Socket::Close()
{
    if( INVALID_SOCKET == this->m_SocketId )
    {
        closesocket(this->m_SocketId);
    }
    return 0;
}

int Socket::Bind(int port)
{
    this->m_bindPort = port;
    m_remoteaddr.sin_family = AF_INET;
    m_remoteaddr.sin_addr.s_addr = htons(INADDR_ANY);   //inet_addr("127.0.0.1");
    m_remoteaddr.sin_port = htons(port);
    return bind(this->m_SocketId,(SOCKADDR*)&m_remoteaddr,sizeof(SOCKADDR));                 //绑定
}

int Socket::Listen(int backlog)
{
    return listen(this->m_SocketId,backlog);
}

Socket Socket::Accept()
{
    Socket remot;
    socklen len = sizeof(SOCKADDR_IN);
    remot.m_SocketId = accept(this->m_SocketId,(sockaddr *)&remot.m_remoteaddr,&len);
    return remot;
}

Socket* Socket::Accept(Socket *socket)
{
    assert( socket != NULL );
    socklen len = sizeof(SOCKADDR_IN);
    socket->m_SocketId = accept(this->m_SocketId,(sockaddr *)&socket->m_remoteaddr,&len);
    return socket;
}

int Socket::Connect(const char *ip, int port)
{
    this->m_ip = ip;
    this->m_port = port;
    return this->Connect();
}

int Socket::Connect(const string &ip, int port)
{
    this->m_ip = ip.c_str();
    this->m_port = port;
    return this->Connect();
}

int Socket::Connect()
{
    this->m_remoteaddr.sin_family = AF_INET;
    this->m_remoteaddr.sin_addr.s_addr = inet_addr( this->m_ip.c_str() );
    this->m_remoteaddr.sin_port = htons(m_port);
    return connect(this->m_SocketId,(const struct sockaddr *)&this->m_remoteaddr,sizeof(m_remoteaddr));
}

int Socket::Reconnect(const char *ip, int port)
{
    this->Close();
    this->Create();
    this->m_ip = ip;
    this->m_port = port;
    return this->Connect();
}

int Socket::Send(const char *buf, int len, int flags)
{
    int lens = (int)(( len == -1 ) ? strlen(buf)+1 : len);
    return send(this->m_SocketId,buf,lens,flags);
}

int Socket::Send(const string &buf, int flags)
{
    return send(this->m_SocketId,buf.c_str(),(int)buf.length()+1,flags);
}

int Socket::Receive(char *buf, int len, int flags)
{
    return recv(this->m_SocketId,buf,len,flags);
}

int Socket::SendTo(char *ip, int port,const char *buf, int len, int flags)
{
    int lens = (int)((len == -1) ? strlen(buf)+1 : len);
    m_remoteaddr.sin_addr.s_addr = inet_addr(ip);
    m_remoteaddr.sin_family = AF_INET;
    m_remoteaddr.sin_port = htons(port);
    return sendto(this->m_SocketId,buf,lens,flags,(const sockaddr *)&m_remoteaddr,sizeof(sockaddr_in));
}

int Socket::SendTo(char *ip, int port,const string &str,int flags)
{
    return this->SendTo(ip,port,str.c_str(),(int)str.length()+1,flags);
}

int Socket::ReceiveFrom(char *buf, int len, Host *host, int flags)
{
    socklen lens = sizeof(sockaddr_in);
    sockaddr_in sockadd;
    int count = recvfrom(this->m_SocketId,buf,len,flags,(sockaddr*)&sockadd,&lens);
    if( NULL != host )
    {
        host->ip = inet_ntoa(sockadd.sin_addr);
        host->port = sockadd.sin_port;
    }
    return count;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

这个是运行在Windows下的客户端代码
#include "Socket.h"
#include <iostream>
using namespace std;

void main()
{
    Socket::InitSocket();
    Socket client;
    client.Connect("172.16.24.247",4128);
    char buf[100];
    while( 1 )
    {
        cout<<"Input string:";
        cin>>buf;
        client.Send(buf);
        client.Receive(buf,100);
        cout<<"Server Say:"<<buf<<endl;
    }
    Socket::ClearSocket();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

下面是运行在Linux下的服务端:

#include "Socket.h"
#include <iostream>
using namespace std;

int main()
{
    Socket server;
    server.Bind(4128);
    server.Listen();
    Socket client;
    server.Accept(&client);
    char buf[100];

    while( 1 )
    {
        client.Receive(buf,100);
        cout<<client.GetIP()<<" Say:"<<buf<<endl;
        cout<<"Input string:";
        cin>>buf;
        client.Send(buf);
    }
}
 

呵呵,付上贴图吧!

技术 | 阅读 3098 次
文章评论,共0条
游客请输入验证码
浏览1940438次