封装naive socket

周五去一个公司打了个酱油,面试官问我:你封装过socket没?

言下之意是问我实际写过底层代码没,我悻悻地说写过点。

PS:说实话木有封装过,今天无聊就来封装下。

话说写了这么久C++,底层用c来写还是灰常爽的,C++把它包起来很好看而且好用。

嗯嗯,言归正传,创建了MyTCPSocket:

问题记录1:一旦来了新的链接,就创建一个work线程来处理,但是遇到了小问题:

#pragma once
#include <winsock.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32.lib")

static DWORD WINAPI WorkerFun(LPVOID aData);

class MyTCPSocket
{
public:
    MyTCPSocket(void);
    ~MyTCPSocket(void);
    bool Init();
    bool UnInit();
    bool CreateSocket();
    bool Bind(unsigned aPost,const char* aAdress);
    bool Listen(int aBacklog=5);
    bool Connect(unsigned aPost,const char* aAdress);
    bool Send(const char* aBuf);
    bool Recv();
    void Accept();

private:
    SOCKET m_Socket;
    SOCKET m_ClientSocket;
    sockaddr_in m_SockClientaddrIn ;
};
#include "MyTCPSocket.h"

MyTCPSocket::MyTCPSocket(void)
:m_Socket(INVALID_SOCKET)
{
}

MyTCPSocket::~MyTCPSocket(void)
{
}

bool MyTCPSocket::Init()
{
    int iResult;
    WORD wVersionRequested;
    WSADATA wsaData;

    wVersionRequested = MAKEWORD(2, 2);
    iResult = WSAStartup(wVersionRequested, &wsaData);
    if (iResult != 0) 
    {
        printf("WSAStartup failed with error: %d
", iResult);
        return false;
    } 
    else 
    {
        printf("WSAStartup succeeded!
");
        return true;
    }
}

bool MyTCPSocket::CreateSocket()
{
    m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (INVALID_SOCKET == m_Socket)
    {
        printf("INVALID_SOCKET
");
        return false;
    }
    printf("Create Socket(%d) successully.
",m_Socket);
    BOOL reuseaddr=TRUE;
    setsockopt(m_Socket,SOL_SOCKET,SO_REUSEADDR,(const char*)&reuseaddr,sizeof(reuseaddr));
    return true;
}

bool MyTCPSocket::Bind(unsigned aPost,const char* aAdress)
{
    struct sockaddr_in server_addr;    // server address information
    server_addr.sin_family = AF_INET;         // host byte order
    server_addr.sin_port = htons(aPost);     // short, network byte order
    server_addr.sin_addr.s_addr = inet_addr(aAdress); // automatically fill with my IP
    memset(server_addr.sin_zero, '', sizeof(server_addr.sin_zero));
    if (-1 == bind(m_Socket,(struct sockaddr *)&server_addr,sizeof(server_addr)))
    {
        printf("Bind Error.
");
        return false;
    }

    int nRecvBuf = 32 * 1024; //设置为32K
    if (setsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }
    return true;
}

bool MyTCPSocket::Connect( unsigned aPost,const char* aAdress )
{
    sockaddr_in lsockaddr_in;
    lsockaddr_in.sin_family = AF_INET;
    lsockaddr_in.sin_port = htons(aPost);
    lsockaddr_in.sin_addr.s_addr = inet_addr(aAdress);

    if (-1 == connect(m_Socket,(struct sockaddr *)&lsockaddr_in,sizeof(lsockaddr_in)))
    {
        printf("Conenct Error.
");
        return false;
    }
    return true;
}

bool MyTCPSocket::Listen( int aBacklog/*=5*/ )
{
    if (-1 == listen(m_Socket,aBacklog))
    {
        printf("Listen Error.
");
        return false;
    }
    return true;
}

bool MyTCPSocket::Send( const char* aBuf)
{
    if (-1 == send(m_Socket,aBuf,strlen(aBuf)+1,0))
    {
        printf("Send Error.
");
        return false;
    }
    return true;
}

bool MyTCPSocket::Recv()
{
    char lBuf[2048];
    int lLength = 0;
    lLength = recv(m_ClientSocket,lBuf,sizeof(lBuf),0);
    if (SOCKET_ERROR == lLength || 0 == lLength)
    {
        closesocket(m_ClientSocket);
        return false;
    }
    int lBegin = 0;
    int lEnd = 0;
    for (;lEnd < lLength;++lEnd)
    {
        if ('' == lBuf[lEnd])
        {
            char lData[1024];
            int lLen = lEnd-lBegin;
            memcpy(lData,lBuf+lBegin,lLen+1);
            printf("We successfully received %d byte: %s.
", lLen, lData);
            lBegin = lEnd+1;
        }
    }
    if (lEnd < lLength)
    {
        char lData[1024];
        memcpy(lData,lBuf+lBegin,lEnd-lBegin);
        lData[lEnd] = '';
        printf("We successfully received %d byte: %s.
", lData);
    }
    return true;
}

bool MyTCPSocket::UnInit()
{
    if (-1 == closesocket(m_Socket))
    {
        printf("Close Socket Error.
");
        return false;
    }
    printf("Close Socket(%d).
",m_Socket);
    return true;
}

void MyTCPSocket::Accept()
{
    int lAddrLen = sizeof(m_SockClientaddrIn);
    m_ClientSocket = accept(m_Socket, (sockaddr*)&m_SockClientaddrIn,&lAddrLen);

    printf("We successfully got a connection from %s:%d.
",
        inet_ntoa(m_SockClientaddrIn.sin_addr), ntohs(m_SockClientaddrIn.sin_port));

    HANDLE handle = ::CreateThread(NULL, 0, WorkerFun,NULL, 0, NULL);
}

DWORD WINAPI WorkerFun( LPVOID aData )
{
    printf("Create Worker Thread.
");

    SOCKET lSocket = (SOCKET)(aData);

    char lBuf[2048];
    int lLength = 0;
    lLength = recv(lSocket,lBuf,sizeof(lBuf),0);
    if (SOCKET_ERROR == lLength || 0 == lLength)
    {
        closesocket(lSocket);
        return false;
    }
    int lBegin = 0;
    int lEnd = 0;
    for (;lEnd < lLength;++lEnd)
    {
        if ('' == lBuf[lEnd])
        {
            char lData[1024];
            int lLen = lEnd-lBegin;
            memcpy(lData,lBuf+lBegin,lLen+1);
            printf("We successfully received %d byte: %s.
", lLen, lData);
            lBegin = lEnd+1;
        }
    }
    if (lEnd < lLength)
    {
        char lData[1024];
        memcpy(lData,lBuf+lBegin,lEnd-lBegin);
        lData[lEnd] = '';
        printf("We successfully received %d byte: %s.
", lData);
    }
    return 0;
}

测试代码:

#include <stdio.h>

#include "MyTCPSocket.h"

void ServerStart() 
{
    MyTCPSocket lServer;
    lServer.Init();
    lServer.CreateSocket();
    lServer.Bind(1234,"192.168.28.1");
    lServer.Listen();
    lServer.Accept();

    while(1)
    {
        if (!lServer.Recv())
        {
            break;
        }
    }
    lServer.UnInit();
}

void ClientStart()
{
    MyTCPSocket lServer;
    lServer.Init();
    lServer.CreateSocket();
    if (!lServer.Connect(1234,"192.168.28.1"))
    {
        lServer.UnInit();
        return;
    }
    for (int i =0; i <10;++i)
    {
        lServer.Send("hell0");
    }
    lServer.UnInit();
}
int main()
{
    ServerStart();
}

表示只是刚开始瞎写,很丑 有木有,赶快改进 有木有!

不过经测试,还是不错滴,博客园有大侠封装的更好的木有,写代码不想注释啊,介个可不可以上首页,大侠猛戳呀,哈哈!

原文地址:https://www.cnblogs.com/xiangshancuizhu/p/3323262.html