windows 网络编程C++类

木马程序C++类

#pragma once是一个比较常用的C/C++杂注,只要在头文件的最开始加入这条杂注,就能够保证头文件只被编译一次。

头文件

#if !defined(_MYTCPTRAN_H_)

#define _MYTCPTRAN_H_

#endif

#if _MSC_VER> 1000

#pragma once

#endif

#include <string>

#include <winsock.h>

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

using namespacestd;

//.........................

#define SOCKETBIND1

#define  SOCKETNOBIND2

#define  SOCKET_TIMEOUT-100

//自己的代码

class CMyTcpTran 

{

public:

    CMyTcpTran();

    virtual~CMyTcpTran();

public:

    staticBOOL InitSocketLibray(intlower,int higver);//初始化winsocke api链接库文件

public:

    //初始化socket操作

    SOCKET InitSocket(intSocketType,string strBindIp,u_shortBindPort,int opt);

    //针对本地监听的程序

    SOCKET myaccept(SOCKET s,structsockaddr* addr,int*addrlen);

    //接受

    intmysend(SOCKET sock,constchar*buf,int len,intflag,int overtime);

    //发送

    intmyrecv(SOCKET sock,char*buf,int len,intflag,int overtime,char*EndMark,BOOL soonflag=FALSE);

private:

    SOCKET m_Socket;

};

文件本身

// MyTcpTran.cp______________p: implementation ofthe CMyTcpTran class.

//

//////////////////////////////////////////////////////////////////////

 

#include <WinSock2.h>

#include <tchar.h>

#include "MyTcpTran.h"

#ifdef _DEBUG

#undef THIS_FILE

static charTHIS_FILE[]=__FILE__;

#define newDEBUG_NEW

#endif

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CMyTcpTran::CMyTcpTran()

{

    m_Socket=INVALID_SOCKET;//初始化套接字为无效套接字

}

CMyTcpTran::~CMyTcpTran()

{

    //暂时不需要

}

BOOL CMyTcpTran::InitSocketLibray(intlower,inthigver)

{

    WORD wVersion=0;

    interret=-1;

    WSADATA wsaData;

    //wVersion=MAKEWORD(2,1); //makeword 将两个8位的字节。。合成一个16位的字so..又理解了

    wVersion=MAKEWORD(lower,higver);

    erret=WSAStartup(wVersion,&wsaData);

    if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)  //makeword   lobyte hibyte

    {

        MessageBox(NULL,_T("版本太低了"),_T("提示"),MB_OK);

        returnFALSE;

    }

    returnTRUE;

}

SOCKET CMyTcpTran::InitSocket(intSocketType,string strBindIp,u_short BindPort,intopt)

{

    SOCKET socketid = INVALID_SOCKET;

    socketid=socket(PF_INET,SOCK_STREAM,0);

    SOCKADDR_IN sockStruct;

    sockStruct.sin_family=AF_INET;

    if(strBindIp.empty())//绑定任意IP

    {

        sockStruct.sin_addr.S_un.S_addr=INADDR_ANY;

    }

    else

    {

        sockStruct.sin_addr.S_un.S_addr=inet_addr(strBindIp.c_str());//又学到一个函数c_str

    }

    sockStruct.sin_port=htons(BindPort);//htons  以及u_short(16bit)正好65535fuck....!!!

    if(SocketType==SOCKETBIND)

    {

        //主动连

        if(connect(socketid,(sockaddr*)&sockStruct,sizeof(sockStruct))==SOCKET_ERROR)

        {

            OutputDebugString(_T("链接错误"));

            closesocket(socketid);

            shutdown(socketid,2);

            socketid=INVALID_SOCKET;

        }

        m_Socket=socketid;

    }

    //监听端口 等待链接

    elseif(SocketType==SOCKETNOBIND)

    {

        if(bind(socketid,(sockaddr*)&sockStruct,sizeof(sockStruct))==INVALID_SOCKET) //绑定

        {

            closesocket(socketid);

            socketid=INVALID_SOCKET;

        }

        else

        {

            if(listen(socketid,SOMAXCONN)==SOCKET_ERROR)   //监听

            {

                closesocket(socketid);

                socketid=INVALID_SOCKET;

            }

        }

        m_Socket=socketid;

    }

    returnsocketid; //完美封装

}

SOCKET CMyTcpTran::myaccept(SOCKET s,structsockaddr* addr,int*addrlen)

{

    SOCKET acpsocket=INVALID_SOCKET;

    acpsocket=accept(s,addr,addrlen);

    returnacpsocket;  //创建一个新的套接字,处理链接

}

int CMyTcpTran::myrecv(SOCKET sock,char*buf,intlen,intflag,intovertime,char*EndMark,BOOL soonflag)

{

    intret;

    intnleft=len;

    intidx=0;

    intnCount=0;

    fd_set readfds; //文件描述符集合

    structtimeval timeout;  //

    timeout.tv_sec=0;

    timeout.tv_usec=500;//

    DWORD s_stime=GetTickCount(); //开机后的秒数

    while(nleft>0)

    {

        MSG msg;

        PeekMessage(&msg,NULL,0,0,PM_REMOVE); //压力泵。。然后压一个删一个。。嘎嘎。。

        if(msg.message==WM_QUIT)

            return0;

        FD_ZERO(&readfds);//0

        FD_SET(sock,&readfds);//加入。。。虽然以前不知道FD_SET 不过今天知道了

        if(select(0,&readfds,NULL,NULL,&timeout)==SOCKET_ERROR)

        {

            returnSOCKET_ERROR;

        }

        DWORD e_time=GetTickCount();

        if(!FD_ISSET(sock,&readfds))

        {

            if(e_time-s_stime>overtime*1000)  //超时

                returnSOCKET_ERROR;

            else

                continue;

        }

        ret=recv(sock,&buf[idx],nleft,flag);//nleftLength of buf. 接受缓存区

        if(soonflag==TRUE)

        {

            returnret;

            //立即返回接受到的字节

        }

        s_stime=e_time;

        if(ret<=0)  //错误处理

        {

            intLastError=GetLastError();

            if((-1 == ret) && (WSAETIMEDOUT == LastError))

                continue;

            if((-1 == ret) && (WSAEWOULDBLOCK== LastError)) //没找到这个错误类型的定义。。

            {

                if(nCount<2000)

                {

                    Sleep(10);

                    nCount++;

                    continue;

                }

            }

            returnret;

        }

        nCount=0;

        nleft-=ret;

        idx+=ret;

        if(EndMark!=NULL && idx>5)

        {

            if(strstr(buf+(idx-5),EndMark)!=NULL//应该是查找EndMark

            {

                break;

            }

        }

 

    }

    returnidx;

}

int CMyTcpTran::mysend(SOCKET sock,constchar*buf,intlen,intflag,intovertime)   //发送了

{

    intret;

    intnLeft=len;

    intidx;

    fd_set readfds;

    structtimeval timeout;

    timeout.tv_sec=0;

    timeout.tv_usec=500;

    DWORD s_time = GetTickCount();

    while(nLeft>0)

    {

        MSG msg;

        PeekMessage(&msg,NULL,0,0,PM_REMOVE);

        if(msg.message==WM_QUIT)

            return0;

        FD_ZERO(&readfds);

        FD_SET(sock,&readfds);

        interrorret=select(0,NULL,&readfds,NULL,&timeout);

        if(errorret==SOCKET_ERROR)

        {

            OutputDebugString(_T("mysendEx socket 错误"));

            returnSOCKET_ERROR;

        }

        DWORD e_time=GetTickCount();

        if(!FD_ISSET(sock,&readfds))

        {

            if(e_time-s_time>overtime*1000)

            {

                OutputDebugString(_T("超时"));

                return0;

            }

            else

            {

                continue;

            }

        }

        ret=send(sock,&buf[idx],nLeft,flag);

        if(ret<=0)

        {

            returnret;

        }

        nLeft-=ret;

        idx+=ret;

    }

    returnlen;

}

类说明

头文件定义了一个类,包括构造函数,析构函数。和5个主要函数。

InitSocketLibray返回BOOL

InitSocket返回SOCKET

Myaccept返回SOCKET

Mysend返回INT

Myrecv返回INT

此外还有私有变量m_Socket;

InitSocketLibray函数

比较简单入参为两个整型,表示winsock版本号。

版本低于2.2就弹出报错。返回FALSE

InitSocket函数

支持4个参数:int SocketType,string strBindIp,u_short BindPort,int opt

第1个参数是连接类型,确定是服务端还是客户端。

如果是SOCKETBIND说明是服务端,如果是SOCKETNOBIND,那么就是客户端。

第2个参数strBindIp是绑定的IP地址。

第3个参数BindPort是绑定的端口

第4个参数Opt是保留参数,暂时没有用处。

如果是服务端则返回一个服务端的SOCKET,如果是客户端则返回一个客户端的SOCKET。

Myaccept函数

输入3个参数,套接字,sockaddr指针和,addrlen.

返回一个新的套接字用户处理链接。

Mysend函数

接受5个参数,分别是套接字,接受缓冲区,长度,flag和overtime.

最后返回发送的字节数,如果发送失败返回负数。

超时或退出返回0.

Myrecv函数

输入参数7个,有服务端套接字,接受缓存区,长度,flag,overtime, EndMark,soonflag

其中soonflag表示立即返回接受到的字节。

如果soonflag为false,返回接受的字节数idx。

如果soonflag为true,则返回指定长度的字节数。

如果出错返回负数。

此外,如果EndMark不会NULL,则会判断是否有EndMark存在,存在则也函数结束。

TIPS

fd_set

select()机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄(不管是socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成,当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一socket或文件发生了可读或可写事件。

FD_ZERO(&set); /*将set清零使集合中不含任何fd*/

FD_SET(fd, &set); /*将fd加入set集合*/

FD_CLR(fd, &set); /*将fd从set集合中清除*/

FD_ISSET(fd, &set); /*在调用select()函数后,用FD_ISSET来检测fd是否在set集合中,当检测到fd在set中则返回真,否则,返回假(0)*/

select

select()的机制中提供一fd_set的数据结构,实际上是一long类型的数组, 每一个数组元素都能与一打开的文件句柄(不管是Socket句柄,还是其他 文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成, 当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执 行了select()的进程哪一Socket或文件可读或可写。主要用于Socket通信当中!

PeekMessage

PeekMessage是一个Windows API函数。该函数为一个消息检查线程消息队列,并将该消息(如果存在)放于指定的结构。

BOOL PeekMessage(

LPMSG IpMsg,

HWND hWnd,

UINT wMSGfilterMin,

UINT wMsgFilterMax,

UINT wRemoveMsg

);

lpMsg

接收消息信息的MSG结构指针。

hWnd

其消息被检查的窗口句柄

wMsgFilterMin

指定被检查的消息范围里的第一个消息。

wMsgFilterMax

指定被检查的消息范围里的最后一个消息。

wRemoveMsg

确定消息如何被处理。此参数可取下列值之一:

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net

猜你喜欢

转载自www.cnblogs.com/swncz/p/10448233.html