1. 程式人生 > >c++實現對windwos 下socket 的封裝(實現封包及拆包處理)--

c++實現對windwos 下socket 的封裝(實現封包及拆包處理)--

SuperSocket.h

#pragma once
#include<string>
#include<iostream>
#include <WINSOCK2.H>
#include "MyThread.h"
#include "SuperThread.h"
using namespace std;
class SuperSocket
{
public:
    typedef struct SockData{
        int id;
        int length;
        const char* content;
    }SockData;
public:
    void Listen(int port);
    bool Connect(string ipStr,int port);
    void Send(SockData* data);
protected:
    virtual void OnAccept(SOCKET* socket){};
    void RollReceive();
    void ListenThread();
    int port;
    virtual void OnReceive(SockData* data){};
    SOCKET tempSocket;
    SuperThread<SuperSocket>* mt;
};
//SuperSocket.cpp
#include "SuperSocket.h"


void SuperSocket::ListenThread()
{
    WORD wVersionRequested;// 定義版本資訊變數
    WSADATA wsaData;//定義資料資訊變數
    SOCKET sockfd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    
    int err;//定義錯誤號變數
    wVersionRequested = MAKEWORD(1,1);//給版本資訊賦值
    err = WSAStartup(wVersionRequested, &wsaData);//給錯誤資訊賦值
    if(err!=0)
    {
        return;//告訴使用者找不到合適的版本
    }
    //確認 Windows Sockets DLL 支援 1.1 版本
    //DLL 版本可以高於 1.1
    //系統返回的版本號始終是最低要求的 1.1,即應用程式與DLL 中可支援的最低版本號
    if(LOBYTE(wsaData.wVersion)!= 1||HIBYTE(wsaData.wVersion)!=1)
    {
        WSACleanup();//告訴使用者找不到合適的版本
        return;
    }
    
    if((sockfd=socket(AF_INET,SOCK_STREAM, IPPROTO_TCP))==-1) 
    {
        if (WSAGetLastError() == WSANOTINITIALISED)
        {
            printf("Error:WSANOTINITIALISED,please Call WSAStartup first\n");
            return;
        }
        else
        {
            int err =WSAGetLastError();
            printf("Bind error:%s,errorcode :%d\n",strerror(errno),err);
            return;
        }
    }
    
    /* 伺服器端填充 sockaddr結構 */ 
    memset(&server_addr,0,sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    server_addr.sin_port=htons(port);
    
    /* 捆綁sockfd描述符 */ 
    if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
    {
        int err = WSAGetLastError();
        cout<<"Bind error:%s,errorcode :"<<strerror(errno)<<endl;;
        return;
    }
    
    /* 監聽sockfd描述符 */
    if(listen(sockfd,5)==-1)
    {
        cout<<"Listen error:"<<strerror(errno)<<endl;
        return;
    }
    while(1)
    {
        /* 伺服器阻塞,直到客戶程式建立連線 */
        int sin_size=sizeof(struct sockaddr_in);
        SOCKET socket;
        cout<<"I am Listen ....."<<endl;
        if((socket=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==INVALID_SOCKET )
        {
            cout<<"Accept error:"<<strerror(errno)<<endl;;
            continue;
        }
        cout<<"Server get connection from "<<inet_ntoa(client_addr.sin_addr)<<endl;;
        this->OnAccept(&socket);
    }
}
void SuperSocket::Listen(int port)
{
    this->port=port;
    //    MyThread mt;
    //    mt.InitThread(this,&SuperSocket::ListenThread);
    //    mt.StartThread();
    this->mt=new SuperThread<SuperSocket>(this,&SuperSocket::ListenThread);
    this->mt->StartThread();
}

bool SuperSocket::Connect(string ipStr,int port)
{
    WSADATA  Ws;
    SOCKET CientSocket;
    struct sockaddr_in ServerAddr;
    int AddrLen = 0;
    HANDLE hThread = NULL;
    
    //Init Windows Socket
    if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
    {
        cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
        return false;
    }
    
    //Create Socket
    CientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if ( CientSocket == INVALID_SOCKET )
    {
        cout<<"Create Socket Failed::"<<GetLastError()<<endl;
        return false;
    }
    
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_addr.s_addr = inet_addr(ipStr.c_str());
    ServerAddr.sin_port = htons(port);
    memset(ServerAddr.sin_zero, 0x00, 8);

    int err = connect(CientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
    if ( err == SOCKET_ERROR )
    {
        cout<<"Connect Error::"<<GetLastError()<<endl;
        return false;
    }
    else
    {
    //    MyThread mt;
    //    mt.InitThread(this,&SuperSocket::RollReceive);
    //    mt.StartThread();
        this->tempSocket=CientSocket;
        SuperThread<SuperSocket> st(this,&SuperSocket::RollReceive);
        st.StartThread();
        return true;
    }
}

void SuperSocket::RollReceive()
{
    int iResult;
    int recvbuflen=1024;
    bool isComplete=true;
    int ID;
    int length;
    int lenReaded;
    int lenLeaved;
    char content[100000];
    while(true)
    {
        if(!isComplete)
        {
            
            iResult=recv(tempSocket,content+lenReaded,lenLeaved,0);
            if(iResult<=0)
            {
                printf("recv failed with error: %d/n", WSAGetLastError());  
                closesocket(this->tempSocket);  
                break;
            }
            lenReaded+=iResult;
            lenLeaved=length-lenReaded;
            if(lenReaded<length)
            {
                isComplete=false;
            }
        }
        else
        {
            iResult=recv(tempSocket,(char*)&ID,sizeof(int),0);
            if(iResult<=0)
            {
                printf("recv failed with error 0: %d/n", WSAGetLastError());  
                closesocket(this->tempSocket);  
                break;
            }
            iResult=recv(tempSocket,(char*)&length,sizeof(int),0);
            if(iResult!=sizeof(int))
            {
                printf("recv failed with error 1: %d/n", WSAGetLastError());  
                closesocket(this->tempSocket);  
                break;
            }
            memset(content,0,length+1);
            iResult=recv(tempSocket,content,length,0);
            if(iResult<=0)
            {
                printf("recv failed with error 2: %d/n", WSAGetLastError());  
                closesocket(this->tempSocket);  
                break;
            }
            lenReaded=length;
            lenLeaved=length-lenReaded;
            if(iResult<length)
            {
                isComplete=false;
            }
        }
        if(lenLeaved<=0)
        {
            isComplete=true;
            SuperSocket::SockData sockData;
            sockData.id=ID;
            sockData.length=length;
            sockData.content=content;
            this->OnReceive(&sockData);
        }        
    }
}

void SuperSocket::Send(SuperSocket::SockData* data)
{
    send(tempSocket,(char*)&data->id,sizeof(int),0);
    send(tempSocket,(char*)&data->length,sizeof(int),0);
    send(tempSocket,data->content,data->length,0);
}
//SuperThread.h
#include<windows.h>


template<typename T>
class SuperThread
{
public:
    SuperThread(T* t,void (T::*f)());
    void StartThread();
    void PauseThread();
    void RestartThread();
    void DestroyThread();
    void WaitForThread();
    static DWORD WINAPI StartRun(void* param);
    T* t;
    void (T::*f)();
    static bool isOk;
private:
//    pthread_t mThread;
    HANDLE handle;
    

};
template<typename T>
bool SuperThread<T>::isOk=false;
template<typename T>
SuperThread<T>::SuperThread(T* t,void (T::*f)())
{
    this->t=t;
    this->f=f;
}
template<typename T>
void SuperThread<T>::StartThread()
{
//    pthread_create(&mThread,NULL,&StartRun,this);
    handle=CreateThread(NULL,0,StartRun,this,0,0);
    while(!this->isOk)
    {
        Sleep(50);
    }
    this->isOk=false;
//    WaitForSingleObject(hMutex,INFINITE);


}
template<typename T>
void SuperThread<T>::PauseThread()
{
}
template<typename T>
void SuperThread<T>::RestartThread()
{
}
template<typename T>
void SuperThread<T>::DestroyThread()
{

}
template<typename T>
void SuperThread<T>::WaitForThread()
{
    //pthread_join(mThread,NULL);
    WaitForSingleObject(handle,INFINITE);
}
template<typename T>
DWORD WINAPI SuperThread<T>::StartRun(void* param)
{
    SuperThread<T>* mt=(SuperThread<T>*) param;
    T *t1=mt->t;
    void (T::*f1)();
    f1=mt->f;
    SuperThread<T>::isOk=true;
    (t1->*f1)();
    return 0;
}
//MySocket.h
#include "SuperSocket.h"

class MySocket:public SuperSocket
{
public:
    MySocket(SOCKET* socket);
    MySocket(){}
protected:
    virtual void OnAccept(SOCKET* socket);
    virtual void OnReceive(SuperSocket::SockData* data);
};
//MySocket.cpp
#include "MySocket.h"
#include "MyThread.h"

void MySocket::OnAccept(SOCKET* socket)
{
    SuperSocket* ss=new MySocket(socket);
    //MyThread* mt=new MyThread(&ms,MySocket::RollReceive);
//    MyThread mt;
//    mt.InitThread(ss,&SuperSocket::RollReceive);
//    mt.StartThread();
    SuperThread<SuperSocket> st(ss,&SuperSocket::RollReceive);
    st.StartThread();
}

MySocket::MySocket(SOCKET* socket)
{
    this->tempSocket=*socket;
}

void MySocket::OnReceive(SuperSocket::SockData* data)
{
    cout<<data->id<<endl;
}
//main.cpp
#include<iostream>
#include<string>
#include "MySocket.h"
using namespace std;
int main()
{
    MySocket  ms;
    ms.Connect("10.10.24.148",8010);
    while(true)
    {
        string s;
        cin>>s;
        MySocket::SockData data;
        data.id=0;
        data.length=s.size();
        data.content=s.c_str();
        ms.Send(&data);
    }
    return 0;
}