计算机网络作业(五)

班级:软件工程二班 姓名:马静 学号:1505060226

一、实验内容
在windows环境下通过编写ping程序,了解ping的功能。
二、实验过程
要实现ping程序需要实现以下步骤:
(1)创建协议类型为IPPRPTO_ICMP的原始套接字,设置套接字属性。
(2)创建并初始化ICMP封包。
(3)调用sendto函数向远程主机发送ICMP请求。
(4)调用recfrom函数接受ICMP响应。
实现以上步骤的源代码如下:

include "stdafx.h"

include "Ping.h"

include "PingDlg.h"

ifdef _DEBUG

define new DEBUG_NEW

undef THIS_FILE

static char THIS_FILE[] = FILE;

endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
CAboutDlg();

// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
//}}AFX_VIRTUAL

// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPingDlg dialog

CPingDlg::CPingDlg(CWnd* pParent /=NULL/)
: CDialog(CPingDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CPingDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CPingDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPingDlg)
DDX_Control(pDX, IDC_ReList, m_ReList);
DDX_Control(pDX, IDC_IP, m_Ip);
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPingDlg, CDialog)
//{{AFX_MSG_MAP(CPingDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_Ping, OnPing)
ON_BN_CLICKED(IDC_Clean, OnClean)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPingDlg message handlers

BOOL CPingDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//GetDlgItem(IDC_Clean)->EnableWindow(false);//清除按钮不能用
m_Ip.SetAddress (172,31,8,232); //初始显示的Ip地址

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
    CString strAboutMenu;
    strAboutMenu.LoadString(IDS_ABOUTBOX);
    if (!strAboutMenu.IsEmpty())
    {
        pSysMenu->AppendMenu(MF_SEPARATOR);
        pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    }
}

// 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
InitSocket();//调用
return TRUE;  // return TRUE  unless you set the focus to a control

}

void CPingDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

// 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 CPingDlg::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 CPingDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}

BOOL CPingDlg::InitSocket()
{ S=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if(S==INVALID_SOCKET)
{ MessageBox("创建套接字失败!");
return FALSE;
}
SOCKADDR_IN addrSock; //自己的地址
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(5555);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
if(bind(S,(SOCKADDR*)&addrSock,sizeof(SOCKADDR))==SOCKET_ERROR)
{ closesocket(S);
MessageBox("绑定失败!");
return FALSE;
}
return TRUE;
}

void CPingDlg::OnPing()
{
// TODO: Add your control notification handler code here
SetTimeout(S, 1000);
unsigned char B[4];
m_Ip.GetAddress(B[0],B[1],B[2],B[3]); //获得编辑框中输入的IP地址

struct in_addr IP;
memcpy(&IP.S_un.S_addr,B,4);

//存放 到 目的端地址 结构体 中
SOCKADDR_IN dest;
dest.sin_family=AF_INET;
dest.sin_port=htons(0);
dest.sin_addr.S_un.S_addr=IP.S_un.S_addr;
//-----------------------------------------------------------------------------------------------
ICMPHeader pIcmp;
char buff[sizeof(ICMPHeader) +5]; //5:要发送的信息占5B
pIcmp=(ICMPHeader
)buff;
// 开始发送和接收ICMP封包
USHORT nSeq = 0;
char recvBuf[1024];
SOCKADDR_IN from;
int nLen = sizeof(from);
for(int nCount = 0;nCount< 4;nCount++)
{ // 填写要发送的ICMP封包数据
pIcmp->icmp_type = 8;
pIcmp->icmp_code = 0;
pIcmp->icmp_id = (unsigned short)GetCurrentProcessId();
pIcmp->icmp_checksum = 0;
pIcmp->icmp_sequence = nSeq++;
pIcmp->icmp_timestamp = GetTickCount();
memset(&buff[sizeof(ICMPHeader)], '0', 5);
pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMPHeader)+5 );
//发送
int nRet = sendto(S, buff,sizeof(ICMPHeader)+5, 0, (SOCKADDR )&dest, sizeof(dest));
if(nRet == SOCKET_ERROR)
{ MessageBox("调用sendto()失败");
break;
}
else
{ //接收
nRet = recvfrom(S, recvBuf, 1024, 0, (sockaddr
)&from, &nLen);
if(nRet == SOCKET_ERROR)
{ if(WSAGetLastError() == 10060)
{ m_ReList.AddString("Request timed out");
continue;
}
MessageBox("调用recvfrom()失败");
break;
}
else
{ ICMPHeader pRecvIcmp;
pRecvIcmp= (ICMPHeader
)(recvBuf + 20);
// 解析接收到的ICMP封包
if(nRet < sizeof(IPHeader) + sizeof(ICMPHeader)+5)
{ m_ReList.AddString("数据在路上部分丢失");
break;
}
else if(pRecvIcmp->icmp_type != 0)
{ m_ReList.AddString("不是我需要的回应");
break;
}
else if(pRecvIcmp->icmp_type== 3)
{ m_ReList.AddString("目的主机不可达");
break;
}
else if(pRecvIcmp->icmp_id != GetCurrentProcessId())
{ m_ReList.AddString("不是发给我的");
break;
}
else
m_ReList.AddString("收到正确回应");
}
}
}
m_ReList.AddString("结束Ping");
GetDlgItem(IDC_Clean)->EnableWindow(true);

}

BOOL CPingDlg::SetTimeout(SOCKET S, int nTime)
{ int ret = setsockopt(S, SOL_SOCKET,SO_RCVTIMEO, (char*)&nTime, sizeof(nTime));
if(ret!=0)
{ char cChar[50];
sprintf(cChar,"错误代码=%d\n",GetLastError());
MessageBox(cChar,"调用setsockopt()失败,ret=");
//MessageBox("调用setsockopt()失败");
exit(0);
}
else return ret;
}

USHORT CPingDlg::checksum(USHORT *buff, int size)
{
u_char buf1=(u_char)buff;
register int cksum = 0;
while(size>1)
{
cksum += *buff++;
size -=2;
}
if(size==1)
cksum += (UCHAR)buff;
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return ((USHORT)~cksum);
}

void CPingDlg::OnClean()
{
// TODO: Add your control notification handler code here
m_Ip.ClearAddress();
m_ReList.ResetContent();

}

运行结果如图:
OH96%B9N1)O0BD1LB51`QKC.png

整个过程演示:
123.gif

三、心得体会
通过仔细阅读程序代码,查找相关资料,我大致了解了程序的基本过程。在此次作业中有很多知识是之前没有学过的,所以找了很多东西,也学习了很多。在做作业的时候也发现了很多问题,代码不会写,自己写的代码太简单,自己的思路太简单,程序出错不想改等等。所以在今后的学习中还是要认真。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容