1、计算机网络课程设计报告实 验 报 告实验名称: 计算机网络课程设计 学生姓名: xxxxxxxxxxxxxxx 专 业: xxxxxxxxxxxxxxx 班 级: xxxxxxxxxxxxxxx 学 号: xxxxxxxxxxxxxxx 指导教师: xxxxxxxxxxxxxxx 实验成绩: 实验地点: 实验时间: 2016 年 5 月 6 日一、实验目的与实验要求1、实验目的 将书本上抽象的概念与具体实现技术结合,通过网络软件编程的实践,深入理解理论课上学习到的ARP、IP、TCP等重要网络协议的原理,通过自己动手编程封装与发送这些数据包,加深对网络协议的理解,掌握协议帧的结构和工作原理及其
2、对协议栈的贡献。2、实验要求 网络课程设计包含两个部分的内容: 题目一是数据包的封装发送和解析(ARP/IP/TCP),要求使用Winpcap技术和Socket技术,根据ARP/IP/TCP帧的结构,封装数据包发送到局域网中。另外要捕获网络中的TCP/IP/ARP数据包,解析数据包的内容,并将结果显示,并同时写入日志文件。 题目二是从可选题目中选择一个,可选题目均是网络应用小程序,要求小组使用网络编程技术设计并实现一个网络应用程序,加深对网络协议协的理解,并锻炼网络编程能力。二、实验设备(环境)及要求1、实验硬件设备:计算机型号:联想ThinkPad T430u处理器型号:Intel i5 主
3、频:1.8Hz网卡型号:(1)Realtek PCIe GBE (2)Broadcom 802.11n2、实验软件要求:操作系统:Windows10应用软件:Visual Studio 2015 Pro3、小组成员及分工:三、实验内容与步骤1、实验1:数据包的封装发送和解析(ARP/IP/TCP)(1)实验内容1)程序目标:根据IP帧的结构,封装IP数据包发送到局域网中。并捕获网络中的IP数据包,解析数据包的内容,并将结果显示,并同时写入日志文件。2)程序功能:以命令行形式运行在标准输出中显示捕获的IP报文的首部字段的内容。使用winpcap访问网卡,手动封装定义IP首部的数据结构填充数据包,
4、发送数据包,捕获数据包使用winpcap,捕获IP数据包(2)主要步骤1)总体设计:a.获取设备列表并打印,打开所选择的适配器;b.准备工作:定义ip相关的结构体、打开要存放结果的文件,设置过滤器,手写ip数据报(内容有无效的MAC源和目的地址,和均为本机地址的ip源地址和目的地址,即发给自己一个ip报文),设置抓到数据报的解析和输出到文件的操作函数(解析ip报,打印并写入文件:报文的版本、协议、源和目的地址等)。c.发包、抓包。d.分析获取的数据。2)具体实现:#define HAVE_REMOTE#include pcap.h#include remote-ext.h#include st
5、dio.h#include stdlib.h/*4字节的IP地址*/typedef struct ip_address u_char byte1; u_char byte2; u_char byte3; u_char byte4;ip_address;/*IPv4首部*/typedef struct ip_header u_char ver_ihl; /版本(4bits)+首部长度(4bits) u_char tos; /服务类型 u_short tlen; /总长类型 u_short identification; /标识 u_short flags_fo; /标志位+段偏移量 u_char
6、 ttl; /存活时间 u_char proto; /协议 u_short crc; /首部校验和 ip_address daddr; /目的地址 ip_address saddr; /源地址 u_int op_pad; /选项与填充ip_header;void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);/* packet handler 函数原型 */void packet_handler(u_char *param, const struct pcap_pk
7、thdr *header, const u_char *pkt_data);int main() pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle; char errbufPCAP_ERRBUF_SIZE; u_int netmask; char packet_filter = ip; /抓包类型 struct bpf_program fcode; pcap_dumper_t *dumpfile; /* 获取本机设备列表 */ if (pcap_findalldevs_ex(PCAP_SRC_IF_STR
8、ING, NULL, &alldevs, errbuf) = -1) fprintf(stderr,Error in pcap_findalldevs: %sn, errbuf); exit(1); /* 打印适配器列表 */ for(d=alldevs; d; d=d-next) printf(%d. %s, +i, d-name); if (d-description) printf( (%s)n, d-description); else printf( (No description available)n); if(i=0) printf(nNo interfaces found!
9、Make sure WinPcap is installed.n); return -1; printf(Enter the interface number (1-%d):,i); scanf(%d, &inum); if(inum i) printf(nInterface number out of range.n); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; /* 跳转到选中的适配器 */ for(d=alldevs, i=0; inext, i+); /* 打开设备 */ if ( (adhandle= pcap_open(d
10、-name, / 设备名 65536, / 65535保证能捕获到不同数据链路层上每个数据包的全部内容 PCAP_OPENFLAG_PROMISCUOUS, / 混杂模式 1000, / 读取超时时间 NULL, / 远程机器验证 errbuf / 错误缓冲池 ) ) = NULL) fprintf(stderr,nUnable to open the adapter. %s is not supported by WinPcapn, d-name); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; /* 打开堆文件*/ dumpfile
11、= pcap_dump_open(adhandle, D:save.txt); if(dumpfile=NULL) fprintf(stderr,nError opening output filen); return -1; /* 检查数据链路层,只考虑以太网 */ if(pcap_datalink(adhandle)!=DLT_EN10MB) fprintf(stderr, nThis program works only on Ethernet networds.n); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; if(d-add
12、resses != NULL) /获得接口第一个地址的掩码 netmask = (struct sockaddr_in *)(d-addresses-netmask)-sin_addr.S_un.S_addr; else /如果接口没有地址,那么我们假设一个C类的掩码 netmask=0xffffff; /编译过滤器 if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask)0) fprintf(stderr,nUnable to compile the packet filter. Check the syntax.n); /释放设备列表
13、 pcap_freealldevs(alldevs); return -1; /设置过滤器 if(pcap_setfilter(adhandle,&fcode)description); /释放设备列表 pcap_freealldevs(alldevs); /*手写数据包*/ u_char packet100; /*假设在以太网上,设置MAC的目的地址为1:1:1:1:1:1*/ packet0=1; packet1=1; packet2=1; packet3=1; packet4=1; packet5=1; /*设置MAC的源地址为2:2:2:2:2:2*/ packet6=2; packe
14、t7=2; packet8=2; packet9=2; packet10=2; packet11=2; /*设置ip类型*/ packet12=0x08; packet13=0x00; packet14=0x45; packet15=0x20; packet16=0x00; packet17=0x28; packet18=0xcb; packet19=0x16; packet20=0x00; packet21=0x00; packet22=0x2e; packet23=0x06; packet24=0x3e; packet25=0xe6; packet26=0xc0;/192 packet27
15、=0xa8;/168 packet28=0x01;/1 packet29=0x64;/100 packet30=0xc0; packet31=0xa8; packet32=0x01; packet33=0x64; packet34=0x8f; packet35=0x50; /*填充剩下的内容*/ for(i=36;its.tv_sec; ltime=localtime(&local_tv_sec); strftime( timestr, sizeof timestr, %H:%M:%S, ltime); /打印数据包的时间戳和长度 printf(%s,%.6d len:%dn, timestr
16、, header-ts.tv_usec, header-len); /获得IP数据包头部的位置 ih = (ip_header*)(pkt_data+14);/以太网头部长度 /* 打印 IP 地址和 UDP 端口 */ printf(版本+首部长度:%u,ih-ver_ihl); printf(协议:%u,ih-proto); printf(首部校验和:%u,ih-crc); printf(目的地址:%u.%u.%u.%u, ih-daddr.byte1,ih-daddr.byte2,ih-daddr.byte3,ih-daddr.byte4); printf(源地址:%u.%u.%u.%u
17、n, ih-saddr.byte1,ih-saddr.byte2,ih-saddr.byte3,ih-saddr.byte4); FILE *fp; fp=fopen(D:jiexi.txt, a+); fprintf(fp,解析结果:); fprintf(fp,版本+首部长度:%u,ih-ver_ihl); fprintf(fp,协议:%u,ih-proto); fprintf(fp,首部校验和:%u,ih-crc); fprintf(fp,目的地址:%u.%u.%u.%u, ih-daddr.byte1,ih-daddr.byte2,ih-daddr.byte3,ih-daddr.byte
18、4); fprintf(fp,源地址:%u.%u.%u.%un, ih-saddr.byte1,ih-saddr.byte2,ih-saddr.byte3,ih-saddr.byte4); fclose(fp);2、实验2:子网内文件传送(1)实验内容(明确的实验内容)设计并实现一个局域网内部的文件传送工具,使用TCP协议进行可靠文件传输。以图形界面运行,不同结点上文件自动同步(2)主要步骤(详细的实验步骤(系统/方法/算法等),图文结合)1)问题定义:实现一个局域网内的文件传送与聊天的软件2)需求分析:局域网内的文件传送应当具备以下功能:在线用户的及时发现和更新选择一对一或者一对多对话模式与
19、选择用户进行聊天和文件传输用户下线通知与更新用户列表3)系统设计:参考飞鸽传书的实现原理,总结设计方案如下:架构设计:本系统采用本地应用程序设计,仅适用于在同一局域网的主机通信;互相发现:本系统运行时启动局域网广播线程,发出包含主机名称、主机IP以及新加入标识符的广播表明自己新加入;用户列表:监听到其他用户的广播信息后更新列表,显示当前在线的用户名和用户IP;更新列表:在系统退出时会广播本机信息,标识表明自己离开,其余在线用户接收到信息后更新提示该用户下线;选择用户:可以单独选择或者多项选择用户列表中的用户;发送消息:选择用户后,在输入框中输入聊天信息,点击“发送”按钮系统会发送UDP数据包给
20、对应用户的ip地址,端口是8011;接受消息:系统实时监听8011端口以接受不同用户发来的消息并展示在聊天窗口中;发送文件:选择指定用户,点击“发送文件”按钮,选择本机相应文件后,与目标用户建立TCP连接,发送字节流。端口为8011;接受文件:监听到有TCP连接请求时建立实时连接,系统提示用户是否接收文件,选择接收后选择相应路径与文件名后进行接收,接收成功后再聊天窗口显示提示信息。4)详细设计:1局域网用户列表的建立:软件启动后定时的使用UDP协议向255.255.255.255这个广播地址发送广播包,端口设置为8001。广播包内容包含主机名、IP、标识符等信息,已启动软件的用户通过8001端
21、口收到此广播包后,就会在自己的用户列表中添加这个用户的用户名、IP地址等信息,从而局域网内的本系统用户都能建立起用户列表;2传送与接收信息:传送聊天信息时同样使用UDP协议,用户填写消息后点击按钮调用发送消息的函数,然后通过8011端口发送UDP包。系统在启动时通过开辟新线程来监听8011端口,时刻监听发送到本机的信息。3发送文件:用户发送文件时建立一个带参数的线程来发送文件,调用相应的TCP发送函数来发送文件,使用的是8001端口,由于协议不同因此与之前的广播并不冲突;4接收文件:软件启动时开启一个线程用来接收文件,此线程在正常工作条件下处于阻塞监听状态,直到收到建立TCP连接的请求,之后提
22、示用户收到文件选择是否接受,之后选择保存路径,进行接收。5用户离开:用户离线时发送一个离线广播包到255.255.255.255的8001端口,包中含有LEAVE的标识符,收到此广播包的用户,根据包中的IP地址删除用户列表中相应的用户信息,并在聊天窗口显示“XXX用户已经离开”;6聊天记录保存:考虑到用户有保存聊天记录的需求,在聊天记录右侧点击“保存”按钮,可以将当前聊天记录保存为txt文件到用户指定目录中。或点击“清空”,清空当前用户聊天记录。5)具体实现:(C#)using System;using System.Collections.Generic;using System.Compo
23、nentModel;using System.Data;using System.Drawing;using System.IO;using System.Linq;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;namespace IPMessage public partial class frmMain : Form /用户实体 public class Use
24、r private string localname; /用户名 public string localName get return localname; set localname = value; private string localip; /用户IP public string localIP get return localip; set localip = value; /用户数组声明 public static List Userslist = new List(); /获得本机名和本机IP public User getInfo() User u = new User();
25、 string localName = Dns.GetHostName();/获取主机名 /Console.WriteLine(主机名:0, localName); u.localName = localName; IPHostEntry localHost = Dns.GetHostEntry(localName); /输出对应的IP地址 IPAddress localIP = null; for (int i = 0; i localHost.AddressList.Length; i+) if (localHost.AddressListi.AddressFamily = Address
26、Family.InterNetwork) localIP = localHost.AddressListi; break; u.localIP = localIP.ToString(); return u; /发送广播消息 public void broadMessage() Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(255.255.255.255), 8001); /设置Broadcast值为表示允许套接字发送广播消息,该值默认为不允许 socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); User u = getInfo(); /标识符为NEW strin