Socket类自封装的实现

37 篇文章 0 订阅

// Socket32.h: interface for the CSocket32 class.
//
//

#if !defined(AFX_SOCKET32_H__0C5B01C7_CACD_44E5_AB92_130605BBD66B__INCLUDED_)
#define AFX_SOCKET32_H__0C5B01C7_CACD_44E5_AB92_130605BBD66B__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifdef _WIN32
#include <WinSock2.h>
typedef int socklen_t ;
#else
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <netdb.h>
#ifndef CONST
#define CONST               const
#endif

typedef unsigned char   u_char;
typedef unsigned short  u_short;
typedef unsigned int    u_int;
typedef unsigned long   u_long;
typedef u_int           SOCKET;

typedef int                 INT;
typedef unsigned int        UINT;
typedef unsigned int        *PUINT;
typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef float               FLOAT;
typedef FLOAT               *PFLOAT;
typedef BOOL            *PBOOL;
typedef BOOL             *LPBOOL;
typedef BYTE            *PBYTE;
typedef BYTE             *LPBYTE;
typedef int             *PINT;
typedef int              *LPINT;
typedef WORD            *PWORD;
typedef WORD             *LPWORD;
typedef long             *LPLONG;
typedef DWORD           *PDWORD;
typedef DWORD            *LPDWORD;
typedef void             *LPVOID;
typedef CONST void       *LPCVOID;

#ifndef _TCHAR_DEFINED
typedef char TCHAR, *PTCHAR;
typedef unsigned char TBYTE , *PTBYTE ;
#define _TCHAR_DEFINED
#endif /* !_TCHAR_DEFINED */

#ifndef VOID
#define VOID void
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
#endif
typedef CHAR *PCHAR;
typedef CHAR *LPCH, *PCH;

typedef CONST CHAR *LPCCH, *PCCH;
typedef CHAR *NPSTR;
typedef CHAR *LPSTR, *PSTR;
typedef CONST CHAR *LPCSTR, *PCSTR;
typedef LPSTR LPTCH, PTCH;
typedef LPSTR PTSTR, LPTSTR;
typedef LPCSTR LPCTSTR;


#ifndef FALSE
#define FALSE               0
#endif

#ifndef TRUE
#define TRUE                1
#endif

#define INVALID_SOCKET  (SOCKET)(~0)
#define SOCKET_ERROR            (-1)
typedef struct in_addr  *LPIN_ADDR;

#define closesocket(x) close(x)


#endif

class CSocket32  
{
    SOCKET m_hSocket;
    
public:
    BOOL Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM , LPCTSTR lpszSocketAddress = NULL );
    int SendTo( const void* lpBuf, int nBufLen, UINT nHostPort, LPCSTR lpszHostAddress = NULL, int nFlags = 0 );
    int ReceiveFrom( void* lpBuf, int nBufLen, char *rSocketAddress, UINT& rSocketPort, int nFlags = 0 );
    
    BOOL Listen( int nConnectionBacklog = 5 )
    {
        return !listen(m_hSocket,nConnectionBacklog);
    }
    int Send( const void* lpBuf, int nBufLen, int nFlags = 0 )
    {
        return send(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags);
    }
    int Receive( void* lpBuf, int nBufLen, int nFlags = 0 )
    {
        return recv(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags);
    }    
    void Close( )
    {
        closesocket(m_hSocket);
    }

    BOOL GetSockName( char*  rSocketAddress, UINT& rSocketPort );
    BOOL GetPeerName(  char* rPeerAddress, UINT& rPeerPort );
    BOOL Accept( CSocket32& rConnectedSocket,  LPSTR lpSockAddr = NULL,UINT *nPort = NULL);
    BOOL Connect( LPCTSTR lpszHostAddress, UINT nHostPort );
        
    CSocket32();
    virtual ~CSocket32();
    
};

#endif // !defined(AFX_SOCKET32_H__0C5B01C7_CACD_44E5_AB92_130605BBD66B__INCLUDED_)

// Socket32.cpp: implementation of the CSocket32 class.
//
//

#include "stdafx.h"
#include "Socket32.h"
#include <assert.h>

//
// Construction/Destruction
//
//构造
CSocket32::CSocket32()
{
#ifdef _WIN32
    WSAData wsaData;
    int err =WSAStartup(0x0202,&wsaData);
    if ( err != 0 )                           
        return;
    if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 )
    {
        WSACleanup( );
        return; 
    }
#endif
    m_hSocket = INVALID_SOCKET;
}
//析构
CSocket32::~CSocket32()
{
    Close();
}
/**********************************************************************/
//1.创建套接字
BOOL CSocket32::Create( UINT nSocketPort, int nSocketType ,LPCTSTR lpszSocketAddress )
{
    assert(m_hSocket == INVALID_SOCKET);//套接字必须首先初始化为空
    m_hSocket = socket(AF_INET,nSocketType,IPPROTO_IP);//然后再创建
    if(    m_hSocket == INVALID_SOCKET)
        return FALSE;

    sockaddr_in addr = {AF_INET,htons(nSocketPort)};
    if (!lpszSocketAddress) //如果用户不指定,则系统分配
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
    else
        addr.sin_addr.s_addr = inet_addr(lpszSocketAddress);
    
    if (!bind(m_hSocket,(sockaddr*)&addr,sizeof(addr)))
        return TRUE;//If no error occurs, bind returns zero
    Close();
    
    return FALSE;
}

//2.发送(针对UDP)
int CSocket32::SendTo( const void* lpBuf, int nBufLen, UINT nHostPort, LPCSTR lpszHostAddress , int nFlags)
{
    sockaddr_in addr = {AF_INET,htons(nHostPort),};
    assert(lpszHostAddress);//UDP 必须指定目的地址
    addr.sin_addr.s_addr = inet_addr(lpszHostAddress);
    return sendto(m_hSocket,(char*)lpBuf,nBufLen,nFlags,(sockaddr*)&addr,sizeof(addr));
}

//3.接收(针对UDP)
int CSocket32::ReceiveFrom( void* lpBuf, int nBufLen, char *rSocketAddress, UINT& rSocketPort, int nFlags )
{
    sockaddr_in from;//必须设一个临时变量,分配内存,接收信息。
    socklen_t fromlen = sizeof(from);//然后才能计算内存长度
    
    int nRet = recvfrom(m_hSocket,(LPSTR)lpBuf,nBufLen,nFlags,(sockaddr*)&from,&fromlen);
    if(nRet <= 0)
        return nRet;
    if(rSocketAddress)
    {
        strcpy(rSocketAddress,inet_ntoa(from.sin_addr));//out
        rSocketPort = htons(from.sin_port);//out
    }

    return nRet;
}

//4.接受请求(针对TCP)
BOOL CSocket32::Accept( CSocket32& rConnectedSocket, LPSTR lpSockAddr ,UINT *nPort )
{
    sockaddr_in addr = {AF_INET};
    socklen_t nLen = sizeof(addr);
    rConnectedSocket.m_hSocket = accept(m_hSocket,(sockaddr*)&addr,&nLen);
    if(rConnectedSocket.m_hSocket == INVALID_SOCKET)
        return FALSE;
    if(lpSockAddr)
    {
        strcpy(lpSockAddr,inet_ntoa(addr.sin_addr));
        *nPort = htons(addr.sin_port);
    }
    return TRUE;    
}

//5.请求连接(针对TCP)
BOOL CSocket32::Connect( LPCTSTR lpszHostAddress, UINT nHostPort )
{
    sockaddr_in addr = {AF_INET,htons(nHostPort)};
    addr.sin_addr.s_addr = inet_addr(lpszHostAddress);
    if (addr.sin_addr.s_addr == INADDR_NONE)//若是有限广播地址,则用本机地址之一
    {
        hostent * lphost = gethostbyname(lpszHostAddress);
        if (lphost != NULL)
            addr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
        else
        {
            //WSAGetLastError();
        //    WSASetLastError(WSAEINVAL);
            return FALSE;
        }
    }
    return !connect(m_hSocket,(sockaddr*)&addr,sizeof(addr));
}

//6.得到本机套接字:IP:Port
BOOL CSocket32::GetSockName( char*  rSocketAddress, UINT& rSocketPort )
{
    sockaddr_in addr;
    socklen_t nLen = sizeof(addr);

    if(SOCKET_ERROR == getsockname(m_hSocket, (sockaddr*)&addr, &nLen))
        return FALSE;
    if(rSocketAddress)
    {
        strcpy(rSocketAddress,inet_ntoa(addr.sin_addr));
        rSocketPort = htons(addr.sin_port);
    }
    return TRUE;
}

//7.得到对方套接字名字:IP:Port
BOOL CSocket32::GetPeerName(  char* rPeerAddress, UINT& rPeerPort )
{
    sockaddr_in addr;
    socklen_t nLen = sizeof(addr);

    if(SOCKET_ERROR == getpeername(m_hSocket, (sockaddr*)&addr, &nLen))
        return FALSE;
    if(rPeerAddress)
    {
        strcpy(rPeerAddress,inet_ntoa(addr.sin_addr));
        rPeerPort = htons(addr.sin_port);
    }
    return TRUE;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的示例代码,用C++封装Socket类,实现了TCP和UDP协议的通信功能。 ```c++ #include <iostream> #include <string> #include <cstring> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> using namespace std; class Socket { public: Socket(int type); ~Socket(); int Bind(const string& ip, unsigned short port); int Listen(int backlog = 5); int Accept(Socket& client); int Connect(const string& ip, unsigned short port); void Close(); int Send(const string& data); int Recv(string& data); private: int _sockfd; int _type; }; Socket::Socket(int type): _type(type) { if (type == SOCK_STREAM) { _sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } else if (type == SOCK_DGRAM) { _sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); } else { _sockfd = -1; } } Socket::~Socket() { Close(); } int Socket::Bind(const string& ip, unsigned short port) { sockaddr_in addr = {}; addr.sin_family = AF_INET; addr.sin_port = htons(port); if (ip.empty()) { addr.sin_addr.s_addr = INADDR_ANY; } else { addr.sin_addr.s_addr = inet_addr(ip.c_str()); } return bind(_sockfd, (sockaddr*)&addr, sizeof(addr)); } int Socket::Listen(int backlog) { return listen(_sockfd, backlog); } int Socket::Accept(Socket& client) { sockaddr_in addr = {}; socklen_t addrlen = sizeof(addr); int sockfd = accept(_sockfd, (sockaddr*)&addr, &addrlen); if (sockfd < 0) { return sockfd; } client._sockfd = sockfd; client._type = _type; return 0; } int Socket::Connect(const string& ip, unsigned short port) { sockaddr_in addr = {}; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip.c_str()); return connect(_sockfd, (sockaddr*)&addr, sizeof(addr)); } void Socket::Close() { if (_sockfd != -1) { close(_sockfd); _sockfd = -1; } } int Socket::Send(const string& data) { return send(_sockfd, data.c_str(), data.size(), 0); } int Socket::Recv(string& data) { char buffer[1024] = {}; int n = recv(_sockfd, buffer, sizeof(buffer), 0); if (n > 0) { data = string(buffer, n); } return n; } int main() { Socket server(SOCK_STREAM); server.Bind("127.0.0.1", 8080); server.Listen(); Socket client(SOCK_STREAM); client.Connect("127.0.0.1", 8080); Socket conn(SOCK_STREAM); server.Accept(conn); string message = "Hello, world!"; client.Send(message); string buffer; conn.Recv(buffer); cout << buffer << endl; return 0; } ``` 以上是一个简单的Socket类的实现,可以通过调用Socket类的方法,实现TCP和UDP协议的通信。其中,Bind方法用于绑定IP地址和端口号,Listen方法用于监听连接请求,Accept方法用于接受客户端连接,Connect方法用于连接到服务端,Send方法用于发送数据,Recv方法用于接收数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值