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

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

nth word temp add ips object invalid protected 數據

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;
}

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