原始套接字头结构定义

来源:互联网 发布:分类信息系统源码 编辑:程序博客网 时间:2024/04/29 04:21

头结构定义

/// @file ping.h/// @brief ping需要的数据结构#ifndef __PING_H_2016_0408__#define __PING_H_2016_0408__#pragma pack(push)#pragma pack(1)#define ICMP_ECHOREPLY  0#define ICMP_HOST_NOTEXIST 3 ///< 主机不存在#define ICMP_ECHOREQ    8// IP Header -- RFC 791typedef struct tagIPHDR{    // u_char  VIHL;        // Version and IHL    u_char h_len:4;         // length of header    u_char version:4;       // Version of IP    u_char  TOS;            // Type Of Service    short   TotLen;         // Total Length    short   ID;             // Identification    short   FlagOff;        // Flags and Fragment Offset    u_char  TTL;            // Time To Live    u_char  Protocol;       // Protocol(tcp, udp, etc.)    u_short Checksum;       // Checksum    struct  in_addr iaSrc;  // Internet Address - Source    struct  in_addr iaDst;  // Internet Address - Destination}IPHDR, *PIPHDR;typedef struct _UDP_HEADER {  USHORT nSourPort ;   // 源端口号16bit  USHORT nDestPort ;   // 目的端口号16bit  USHORT nLength ;     // 数据包长度16bit  USHORT nCheckSum ;   // 校验和16bit}UDP_HEADER, *PUDP_HEADER;typedef struct _TCP_HEADER {  USHORT nSourPort; // 源端口号16bit  USHORT nDestPort; // 目的端口号16bit  UINT nSequNum; // 序列号32bit  UINT nAcknowledgeNum; // 确认号32bit  // USHORT nHLenAndFlag; // 前4位:TCP头长度;中6位:保留;后6位:标志位16bit  USHORT nTcpLen:4;  USHORT nTcpUnused:6;  USHORT nTcpFlag:6;  USHORT nWindowSize; // 窗口大小16bit  USHORT nCheckSum; // 检验和16bit  USHORT nrgentPointer; // 紧急数据偏移量16bit}TCP_HEADER, *PTCP_HEADER;// ICMP Header - RFC 792typedef struct tagICMPHDR{    u_char  Type;           // Type    u_char  Code;           // Code    u_short Checksum;       // Checksum    u_short ID;             // Identification    u_short Seq;            // Sequence    // char Data;           // Data    ULONG   Data;           // Data, for GetTickCount}ICMPHDR, *PICMPHDR;#define REQ_DATASIZE 32     // Echo Request Data size// ICMP Echo Requesttypedef struct tagECHOREQUEST{    ICMPHDR icmpHdr;//  DWORD   dwTime;    char    cData[REQ_DATASIZE];}ECHOREQUEST, *PECHOREQUEST;// ICMP Echo Replytypedef struct tagECHOREPLY{    IPHDR   ipHdr;    ECHOREQUEST echoRequest;    char    cFiller[256];}ECHOREPLY, *PECHOREPLY;#pragma pack(pop)#endif // #ifndef __PING_H_2016_0408__

应用-ping

// pingUIDlg.h : header file//#if !defined(AFX_PINGUIDLG_H__C679F26E_6016_4CEE_8821_677F00F4C247__INCLUDED_)#define AFX_PINGUIDLG_H__C679F26E_6016_4CEE_8821_677F00F4C247__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include "MyThread.h"#include <list>using namespace std;/////////////////////////////////////////////////////////////////////////////// CPingUIDlg dialogclass CPingUIDlg : public CDialog{// Constructionpublic:    CPingUIDlg(CWnd* pParent = NULL);   // standard constructor// Dialog Data    //{{AFX_DATA(CPingUIDlg)    enum { IDD = IDD_PINGUI_DIALOG };    CListBox    m_CtrlListBoxMsg;    CString m_strIpOrDoMainName;    //}}AFX_DATA    // ClassWizard generated virtual function overrides    //{{AFX_VIRTUAL(CPingUIDlg)    protected:    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support    //}}AFX_VIRTUAL// Implementationprotected:    HICON m_hIcon;    // Generated message map functions    //{{AFX_MSG(CPingUIDlg)    virtual BOOL OnInitDialog();    afx_msg void OnPaint();    afx_msg HCURSOR OnQueryDragIcon();    afx_msg void OnButtonPing();    afx_msg void OnDestroy();    //}}AFX_MSG    afx_msg void OnShowThreadMsg(WPARAM wParam, LPARAM lParam);    DECLARE_MESSAGE_MAP()public:    static unsigned __stdcall ThreadProcPing(void* pParam);    unsigned ThreadProcPing();private:    void DataInit();    void DataUnInit();    void ShowErrMsg(int iErrSn);    void ShowSocketErrMsg();    void ShowErrMsg();    void ShowThreadMsg(TCHAR* pMsg);    void ClearThreadMsg();    void ShowUiMsg(TCHAR* pcMsg);    void Ping(LPCSTR pstrHost);    int SendEchoRequest(SOCKET s, LPSOCKADDR_IN lpstToAddr);    int WaitForEchoReply(SOCKET s);    DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL, DWORD& dwTimeSent);    u_short in_cksum(u_short *addr, int len);private:    list<CString> m_ListDispMsg;    CRITICAL_SECTION g_csDispMsg;    CMyThread m_ThreadProcPing;};//{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_PINGUIDLG_H__C679F26E_6016_4CEE_8821_677F00F4C247__INCLUDED_)
// pingUIDlg.cpp : implementation file//#include "stdafx.h"#include <atlconv.h>#include "pingUI.h"#include "pingUIDlg.h"#include "ping.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif#define WM_SHOW_THREAD_MSG (WM_APP + 1000)/////////////////////////////////////////////////////////////////////////////// CPingUIDlg dialogCPingUIDlg::CPingUIDlg(CWnd* pParent /*=NULL*/)    : CDialog(CPingUIDlg::IDD, pParent){    //{{AFX_DATA_INIT(CPingUIDlg)    m_strIpOrDoMainName = _T("192.168.2.60");    //}}AFX_DATA_INIT    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CPingUIDlg::DoDataExchange(CDataExchange* pDX){    CDialog::DoDataExchange(pDX);    //{{AFX_DATA_MAP(CPingUIDlg)    DDX_Control(pDX, IDC_LIST_MSG, m_CtrlListBoxMsg);    DDX_Text(pDX, IDC_EDIT_IP_OR_DOMAIN_NAME, m_strIpOrDoMainName);    //}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CPingUIDlg, CDialog)    //{{AFX_MSG_MAP(CPingUIDlg)    ON_WM_PAINT()    ON_WM_QUERYDRAGICON()    ON_BN_CLICKED(IDC_BUTTON_PING, OnButtonPing)    ON_WM_DESTROY()    //}}AFX_MSG_MAP    ON_MESSAGE(WM_SHOW_THREAD_MSG, OnShowThreadMsg)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CPingUIDlg message handlersBOOL CPingUIDlg::OnInitDialog(){    CDialog::OnInitDialog();    // Set the icon for this dialog.  The framework does this automatically    //  when the application's main window is not a dialog    SetIcon(m_hIcon, TRUE);         // Set big icon    SetIcon(m_hIcon, FALSE);        // Set small icon    // TODO: Add extra initialization here    DataInit();    return TRUE;  // return TRUE  unless you set the focus to a control}// If you add a minimize button to your dialog, you will need the code below//  to draw the icon.  For MFC applications using the document/view model,//  this is automatically done for you by the framework.void CPingUIDlg::OnPaint() {    if (IsIconic())    {        CPaintDC dc(this); // device context for painting        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);        // Center icon in client rectangle        int cxIcon = GetSystemMetrics(SM_CXICON);        int cyIcon = GetSystemMetrics(SM_CYICON);        CRect rect;        GetClientRect(&rect);        int x = (rect.Width() - cxIcon + 1) / 2;        int y = (rect.Height() - cyIcon + 1) / 2;        // Draw the icon        dc.DrawIcon(x, y, m_hIcon);    }    else    {        CDialog::OnPaint();    }}// The system calls this to obtain the cursor to display while the user drags//  the minimized window.HCURSOR CPingUIDlg::OnQueryDragIcon(){    return (HCURSOR) m_hIcon;}void CPingUIDlg::OnButtonPing() {    UpdateData(TRUE);    if (m_strIpOrDoMainName.IsEmpty()) {        ShowThreadMsg(_T("请输入IP或域名"));    } else {        if (m_ThreadProcPing.IsRunning()) {            ShowThreadMsg(_T("ping任务还没有结束, 请稍等"));        } else {            m_ThreadProcPing.SetParam(                ThreadProcPing,                NULL,                NULL,                this);            m_ThreadProcPing.Start();        }    }}unsigned __stdcall CPingUIDlg::ThreadProcPing(void* pParam) {    if (NULL == pParam) {        return S_FALSE;    }    return ((CPingUIDlg*)pParam)->ThreadProcPing();}unsigned CPingUIDlg::ThreadProcPing() {    ClearThreadMsg();    Ping((LPCTSTR)m_strIpOrDoMainName);    ShowThreadMsg(_T("==========任务结束=========="));    return S_OK;}void CPingUIDlg::OnDestroy() {    CDialog::OnDestroy();    // TODO: Add your message handler code here    m_ThreadProcPing.Stop();    DataUnInit();}void CPingUIDlg::DataInit() {    WSADATA m_WSAData;    WSAStartup(MAKEWORD(2,2), &m_WSAData);    InitializeCriticalSection(&g_csDispMsg);}void CPingUIDlg::DataUnInit() {    DeleteCriticalSection(&g_csDispMsg);    WSACleanup();}void CPingUIDlg::OnShowThreadMsg(WPARAM wParam, LPARAM lParam) {    CString str;    EnterCriticalSection(&g_csDispMsg);    if (0 == wParam) {        while (!m_ListDispMsg.empty()) {            str = m_ListDispMsg.front();            m_ListDispMsg.pop_front();            ShowUiMsg((LPTSTR)(LPCTSTR)str);        }    } else {        m_CtrlListBoxMsg.ResetContent();    }    LeaveCriticalSection(&g_csDispMsg);}void CPingUIDlg::ShowUiMsg(TCHAR* pcMsg) {    int iRc = 0;    if (NULL != pcMsg) {        iRc = m_CtrlListBoxMsg.AddString(pcMsg);        if (LB_ERRSPACE == iRc) {            m_CtrlListBoxMsg.ResetContent();            m_CtrlListBoxMsg.AddString(pcMsg);        }    }}void CPingUIDlg::ShowSocketErrMsg() {    int iErrSn = WSAGetLastError();    ShowErrMsg(iErrSn);}void CPingUIDlg::ShowErrMsg() {    int iErrSn = GetLastError();    ShowErrMsg(iErrSn);}void CPingUIDlg::ShowErrMsg(int iErrSn) {    LPVOID lpMsgBuf = NULL;    FormatMessage(         FORMAT_MESSAGE_ALLOCATE_BUFFER |         FORMAT_MESSAGE_FROM_SYSTEM |         FORMAT_MESSAGE_IGNORE_INSERTS,        NULL,        iErrSn,        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language        (LPTSTR) &lpMsgBuf,        0,        NULL);    if (NULL != lpMsgBuf) {        ShowThreadMsg((LPTSTR)lpMsgBuf);    }    LocalFree(lpMsgBuf);}void CPingUIDlg::ShowThreadMsg(TCHAR* pMsg) {    if (NULL != pMsg) {        EnterCriticalSection(&g_csDispMsg);        m_ListDispMsg.push_back(pMsg);        LeaveCriticalSection(&g_csDispMsg);        PostMessage(WM_SHOW_THREAD_MSG, 0, 0);    }}void CPingUIDlg::ClearThreadMsg() {    EnterCriticalSection(&g_csDispMsg);    m_ListDispMsg.clear();    LeaveCriticalSection(&g_csDispMsg);    PostMessage(WM_SHOW_THREAD_MSG, 1, 0);}void CPingUIDlg::Ping(LPCSTR pstrHost){    CString str;    SOCKET    rawSocket;    LPHOSTENT lpHost;    struct    sockaddr_in saDest;    struct    sockaddr_in saSrc;    DWORD     dwTimeSent = 0;    DWORD     dwElapsed = 0;    DWORD dwTick = 0;    u_char    cTTL;    int       nLoop;    int       nRet;    DWORD dwReplyType = ICMP_ECHOREPLY;    // Create a Raw socket    rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);    if (rawSocket == SOCKET_ERROR)     {        ShowSocketErrMsg();        return;    }    // Lookup host    lpHost = gethostbyname(pstrHost);    if (lpHost == NULL)    {        str.Format(_T("\nHost not found: %s"), pstrHost);        ShowThreadMsg((LPTSTR)(LPCTSTR)str);        return;    }    // Setup destination socket address    saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));    saDest.sin_family = AF_INET;    saDest.sin_port = 0;    // Tell the user what we're doing    str.Format(_T("Pinging %s [%s] with %d bytes of data:\n"),                pstrHost,                inet_ntoa(saDest.sin_addr),                REQ_DATASIZE);    ShowThreadMsg((LPTSTR)(LPCTSTR)str);    // Ping multiple times    for (nLoop = 0; nLoop < 4; nLoop++)    {        // Send ICMP echo request        SendEchoRequest(rawSocket, &saDest);        // Use select() to wait for data to be received        nRet = WaitForEchoReply(rawSocket);        if (nRet == SOCKET_ERROR)        {            ShowSocketErrMsg();            break;        }        if (!nRet)        {            ShowThreadMsg("TimeOut");            continue;        }        // Receive reply        dwReplyType = RecvEchoReply(rawSocket, &saSrc, &cTTL, dwTimeSent);        if (ICMP_ECHOREPLY == dwReplyType) {            // Calculate elapsed time            dwTick = GetTickCount();            dwElapsed = dwTick - dwTimeSent;            str.Format(_T("\nReply from: %s: bytes=%d time=%ldms TTL=%d"),                 inet_ntoa(saSrc.sin_addr),                 REQ_DATASIZE,                dwElapsed,                cTTL);        } else if (ICMP_HOST_NOTEXIST == dwReplyType) {            str = _T("无法访问目标主机");        } else {            str.Format(_T("ICMP回答类型为%d, 请联系软件开发者"), dwReplyType);        }        ShowThreadMsg((LPTSTR)(LPCTSTR)str);    }    nRet = closesocket(rawSocket);    if (nRet == SOCKET_ERROR)        ShowSocketErrMsg();}int CPingUIDlg::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr){    static ECHOREQUEST echoReq;    static nId = 1;    static nSeq = 1;    int nRet;    // Fill in echo request    echoReq.icmpHdr.Type        = ICMP_ECHOREQ;    echoReq.icmpHdr.Code        = 0;    echoReq.icmpHdr.Checksum    = 0;    echoReq.icmpHdr.ID          = nId++;    echoReq.icmpHdr.Seq         = nSeq++;    // Fill in some data to send    for (nRet = 0; nRet < REQ_DATASIZE; nRet++)        echoReq.cData[nRet] = ' '+nRet;    // Save tick count when sent    echoReq.icmpHdr.Data = GetTickCount();    // Put data in packet and compute checksum    echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST));    // Send the echo request                                      nRet = sendto(s,                        /* socket */                 (LPSTR)&echoReq,           /* buffer */                 sizeof(ECHOREQUEST),                 0,                         /* flags */                 (LPSOCKADDR)lpstToAddr, /* destination */                 sizeof(SOCKADDR_IN));   /* address length */    if (nRet == SOCKET_ERROR)         ShowSocketErrMsg();    return (nRet);}int CPingUIDlg::WaitForEchoReply(SOCKET s){    struct timeval Timeout;    fd_set readfds;    readfds.fd_count = 1;    readfds.fd_array[0] = s;    Timeout.tv_sec = 5;    Timeout.tv_usec = 0;    return(select(1, &readfds, NULL, NULL, &Timeout));}DWORD CPingUIDlg::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL, DWORD& dwTimeSent) {    CString str;    ECHOREPLY echoReply;    int nRet;    int nAddrLen = sizeof(struct sockaddr_in);    // Receive the echo reply    ZeroMemory(&echoReply, sizeof(echoReply));    nRet = recvfrom(s,                  // socket                    (LPSTR)&echoReply,  // buffer                    sizeof(ECHOREPLY),  // size of buffer                    0,                  // flags                    (LPSOCKADDR)lpsaFrom,   // From address                    &nAddrLen);         // pointer to address len    // Check return value    if (nRet == SOCKET_ERROR)         ShowSocketErrMsg();    // return time sent and IP TTL    if (echoReply.echoRequest.icmpHdr.Type == ICMP_ECHOREPLY) {        *pTTL = echoReply.ipHdr.TTL;        dwTimeSent = echoReply.echoRequest.icmpHdr.Data;    }    return echoReply.echoRequest.icmpHdr.Type;}//// Mike Muuss' in_cksum() function// and his comments from the original// ping program//// * Author -// *    Mike Muuss// *    U. S. Army Ballistic Research Laboratory// *    December, 1983/* *          I N _ C K S U M * * Checksum routine for Internet Protocol family headers (C Version) * */u_short CPingUIDlg::in_cksum(u_short *addr, int len){    register int nleft = len;    register u_short *w = addr;    register u_short answer;    register int sum = 0;    /*     *  Our algorithm is simple, using a 32 bit accumulator (sum),     *  we add sequential 16 bit words to it, and at the end, fold     *  back all the carry bits from the top 16 bits into the lower     *  16 bits.     */    while( nleft > 1 )  {        sum += *w++;        nleft -= 2;    }    /* mop up an odd byte, if necessary */    if( nleft == 1 ) {        u_short u = 0;        *(u_char *)(&u) = *(u_char *)w ;        sum += u;    }    /*     * add back carry outs from top 16 bits to low 16 bits     */    sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */    sum += (sum >> 16);         /* add carry */    answer = ~sum;             /* truncate to 16 bits */    return (answer);}
0 0
原创粉丝点击