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; }
醉过海阔天空,且狂且痴且醉趁年少