资源描述
题目:
简述Tcp/IP 协议簇运作过程 (包含ARP ICMP IP TCP UDP) 每个协议挑选1-2个代码情景,简析协议内容的代码实现。
TCP/IP:
Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。TCP/IP 定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。通俗而言:TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。而IP是给因特网的每一台联网设备规定一个地址。
IP
IP层接收由更低层(网络接口层例如以太网设备驱动程序)发来的数据包,并把该数据包发送到更高层---TCP或UDP层;相反,IP层也把从TCP或UDP层接收来的数据包传送到更低层。IP数据包是不可靠的,因为IP并没有做任何事情来确认数据包是否按顺序发送的或者有没有被破坏,IP数据包中含有发送它的主机的地址(源地址)和接收它的主机的地址(目的地址)。
高层的TCP和UDP服务在接收数据包时,通常假设包中的源地址是有效的。也可以这样说,IP地址形成了许多服务的认证基础,这些服务相信数据包是从一个有效的主机发送来的。IP确认包含一个选项,叫作IP source routing,可以用来指定一条源地址和目的地址之间的直接路径。对于一些TCP和UDP的服务来说,使用了该选项的IP包好像是从路径上的最后一个系统传递过来的,而不是来自于它的真实地点。这个选项是为了测试而存在的,说明了它可以被用来欺骗系统来进行平常是被禁止的连接。那么,许多依靠IP源地址做确认的服务将产生问题并且会被非法入侵。
TCP:
TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端的通讯。
TCP提供的是一种可靠的数据流服务,采用“带重传的肯定确认”技术来实现传输的可靠性。TCP还采用一种称为“滑动窗口”的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度。
如果IP数据包中有已经封好的TCP数据包,那么IP将把它们向‘上’传送到TCP层。TCP将包排序并进行错误检查,同时实现虚电路间的连接。TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。
TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。应用程序轮流将信息送回TCP层,TCP层便将它们向下传送到IP层,设备驱动程序和物理介质,最后到接收方。
面向连接的服务(例如Telnet、FTP、rlogin、X Windows和SMTP)需要高度的可靠性,所以它们使用了TCP。DNS在某些情况下使用TCP(发送和接收域名数据库),但使用UDP传送有关单个主机的信息。
主要特点:
(1)TCP/IP协议不依赖于任何特定的计算机硬件或操作系统,提供开放的协议标准,即使不考虑Internet,TCP/IP协议也获得了广泛的支持。所以TCP/IP协议成为一种联合各种硬件和软件的实用系统。
(2)TCP/IP协议并不依赖于特定的网络传输硬件,所以TCP/IP协议能够集成各种各样的网络。用户能够使用以太网(Ethernet)、令牌环网(Token Ring Network)、拨号线路(Dial-up line)、X.25网以及所有的网络传输硬件。
(3)统一的网络地址分配方案,使得整个TCP/IP设备在网中都具有惟一的地址
(4)标准化的高层协议,可以提供多种可靠的用户服务。
代码实现:
#include<Winsock2.h>
#include<stdio.h>
#define DEFAULT_PORT 5050
#define DATA_BUFFER 1024
void main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET sClient;
int iPort=DEFAULT_PORT;
int iLen;
char buf[DATA_BUFFER];
struct sockaddr_in ser;
if(argc<2)
{
printf("Usage:client[server IP address]\n");
return;
}
memset(buf,0,sizeof(buf));
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
printf("Failed to load Winsock.\n");
return;
}
ser.sin_family=AF_INET;
ser.sin_port=htons(iPort);
ser.sin_addr.s_addr=inet_addr(argv[1]);
sClient=socket(AF_INET,SOCK_STREAM,0);
if(sClient==INVALID_SOCKET)
{
printf("socket() Failed:%d\n",WSAGetLastError());
return;
}
if(connect(sClient,(struct sockaddr*)&ser,sizeof(ser))==INVALID_SOCKET)
{
printf("connect() Failed:%d\n",WSAGetLastError());
return;
}
else
{
iLen=recv(sClient,buf,sizeof(buf),0);
if(iLen==0)
return;
else if(iLen==SOCKET_ERROR)
{
printf("recv() Failed:%d\n",WSAGetLastError());
return;
}
printf("recv() data from server:%s\n",buf);
}
closesocket(sClient);
WSACleanup();
}
ARP:
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。地址解析协议是建立在网络中各个主机互相信任的基础上的,网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存;由此攻击者就可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗。ARP命令可用于查询本机ARP缓存中IP地址和MAC地址的对应关系、添加或删除静态对应关系等。相关协议有RARP、代理ARP。NDP用于在IPv6中代替地址解析协议.
代码实现
#include<stdio.h>
#include"packet32.h"
#include<winsock2.h>
#pragma comment(lib,"ws2_32")
#pragma comment(lib,"packet")
#define EPT_ARP 0x0806 //定义了一些在构造包的时候要用到的常量
#define EPT_IP 0x0800
#define ARP_HARDWARE 0X0001
#define ARP_REPLY 0x0002
#define ARP_REQUEST 0x0001
#pragma pack(push,1) //在定义结构的时候一顶要用到pack(push,1)和下面的pack(pop)
//否则你构造的结构的长度会有问题
typedef struct ethhdr //以太网头部,长度14
{
unsigned char dst[6]; //目的的MAC地址
unsigned char src[6]; //源的MAC地址
unsigned short type; //帧类型
}ETHHDR,*PETHDHR;
typedef struct eth_arphdr //以太网arp字段长度28
{
unsigned short arp_hrd; //硬件类型
unsigned short arp_pro; //协议类型
unsigned char arp_hln; //硬件地址长度(6)
unsigned char arp_pln; //协议地址长度(4)
unsigned short arp_op; //回应还是请求
unsigned char arp_sha[6]; //发送者MAC地址
unsigned long arp_spa; //发送者IP
unsigned char arp_tha[6]; //接收者MAC地址
unsigned long arp_tpa; //接收者IP
}ETH_ARPHDR,*PETH_ARPHDR;
typedef struct arp //整个ARP包的结构
{
ETHHDR ethhdr;
ETH_ARPHDR eth_arp;
}ARP,*PARP;
#pragma pack(pop)
#define Max_Num_Adapter 10
char AdapterList[Max_Num_Adapter][1024]; //定义的网络适配器列表
int main (int argc,char* argv[])
{
LPADAPTER lpAdapter = 0;
LPPACKET lpPacket;
int i;
DWORD dwErrorCode;
WCHAR AdapterName[8192];
WCHAR *temp,*temp1; //将AdapterNames的内容转存到AdapterList时用
int AdapterNum=0;
ULONG AdapterLength;
ARP arpPacket; //定义的包结构实例
char szPktBuf[256000]; //用于存放包的内容
printf("%d\n",sizeof(ETHHDR)); //这3行是我在测试结构长度时用的,如果没有使用之
printf("%d\n",sizeof(ETH_ARPHDR)); //前说的pack(push,1),pack(pop)长度就成了14,32
printf("%d\n",sizeof(ARP)); //48,与我们的arp包的格式不符
i=0;
AdapterLength = sizeof(AdapterName);
if(PacketGetAdapterNames((char *)AdapterName,&AdapterLength)==FALSE)//获取所有网络适配器
{
printf("Unable to retrieve the list of the adapters!\n");
return -1;
}
temp=AdapterName;
temp1=AdapterName;
while ((*temp!='\0')||(*(temp-1)!='\0')) //将AdapterNames的内容转存到AdapterList
{
if (*temp=='\0')
{
memcpy(AdapterList[i],temp1,(temp-temp1)*2);
temp1=temp+1;
i++;
}
temp++;
}
ICMP:
ICMP是(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用
代码实现
#include <winsock2.h>
#include <ws2tcpip.h>
#define IP_RECORD_ROUTE 0x7
#define DEF_PACKET_SIZE 32 //缺省包长度
#define MAX_PACKET 1024//最大ICMP包长度
#define MAX_IP_HDR_SIZE 60 //最大IP头长度
#define ICMP_ECHO 8 //ICMP回向次数
#define ICMP_ECHOREPLY 0
#define ICMP_MIN 8 //最小8字节的包头
//IP头结构
typedef struct _iphdr
{
unsigned int h_len:4; //头长度
unsigned int version:4;//IP版本
unsigned char tos; //服务类型
unsigned short total_len;//包的总长度
unsigned short ident; //包标识身份
unsigned short frag_and_flags;//标志
unsigned char ttl; //包生命周期
unsigned char proto; //协议类型
unsigned short checksum; //IP校验
unsigned int sourceIP; //源IP
unsigned int destIP; //目标IP
}IpHeader;
//ICMP头结构
typedef struct _icmphdr
{
BYTE i_type;//类型
BYTE i_code;//代码
USHORT i_cksum;//校验和
USHORT i_id;//标识符
USHORT i_seq;//序列号
ULONG timestamp;//时间戳
}IcmpHeader;
//IP头选项结构,当socket可选项设置成IP_OPTIONS时使用该结构
typedef struct _ipoptionhdr
{
unsigned char code; //可选类型
unsigned char len;
unsigned char ptr;
unsigned long addr[9];//IP地址
}IpOptionHeader;
class CPingDlg;
//ICMP服务器封装成一个类CPing
class CPing
{
public:
// 设置Ping参数
void SetConfigure(char *host,BOOL recordrout=FALSE,int size=DEF_PACKET_SIZE);
//解析IP可选参数
void DecodeIPOptions(char* buf,int bytes);
//清除ICMP包
void Cleanup();
//Ping函数
void Ping(int timeout=1000);
//发送ICMP包的Socket
SOCKET m_hSocket;
IpOptionHeader m_ipopt;//
SOCKADDR_IN m_addrDest;//目的地址
SOCKADDR_IN m_addrFrom;//源地址
char *icmp_data;
char *recvbuf;
USHORT seq_no;
char *Ipdest;
int datasize;
BOOL m_bRecordRout;
CPingDlg *m_dlg;
CPing(CPingDlg *dlg);
virtual ~CPing();
private:
//解析ICMP头结构
void DecodeICMPHeader(char*buf,int bytes,SOCKADDR_IN* from);
//校验数据
USHORT checksum(USHORT *buffer,int size);
//填充ICMP数据
void FillICMPData(char*icmp_data,int datasize);
};
UDP:
UDP 是User Datagram Protocol的简称, 中文名是用户数据包协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。UDP在IP报文的协议号是17。
代码实现:
// UDP.h: interface for the UDP class.
//
//////////////////////////////////////////////////////////////////////
#ifndef _ZH_DUP_CE_H_
#define _ZH_DUP_CE_H_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "WinSock.h"
#pragma pack(push,1)
//UDP客户端发送错误回调函数
typedef void (CALLBACK *ONZhUDPERROR)(CWnd *,int);
//UDP客户端接收数据回调函数
typedef void (CALLBACK *ONZhUDPRECV)(CWnd *,char *buf,int bufLen,sockaddr *);
class UDP
{
public:
UDP();
virtual ~UDP();
public:
DWORD Open(CWnd *pWnd,int localPort, LPCTSTR remoteHost ,int remotePort);
DWORD Close(void);
bool SendData(const char *pBuf,int len);
BOOL IsSocketOpen(void);
// UDP 错误事件
ONZhUDPERROR m_OnUdpError;
// UDP 数据接收事件
ONZhUDPRECV m_OnUdpRecv;
private:
SOCKET m_UDPSocket;
struct sockaddr_in m_RemoteAddr; // 存储远程通讯地址
HANDLE m_ExitThreadEvent; // 线程退出事件
CWnd *m_pOwnerWnd; // 存储父窗体句柄
BOOL m_bIsOpen;
static UINT RecvThread(LPVOID lparam);
};
#pragma pack(pop)
#endif
// UDP.cpp: implementation of the UDP class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "zhUDPCE.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define ZHUDP_BUFFER_SIZE 1024
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
UDP::UDP()
{
m_bIsOpen = FALSE;
}
UDP::~UDP()
{
}
/*
* 功能:打开UDP通讯端口
* 返回值:1代表成功;-1,-2,-3等都代表失败
*/
DWORD UDP::Open(CWnd* pWnd, // 父窗体指针
int localPort, // 远程UDP端口
LPCTSTR remoteHost, // 远程IP地址
int remotePort) // 远程UDP端口
{
WSADATA wsa;
m_pOwnerWnd = pWnd;
if(WSAStartup(MAKEWORD(1,1),&wsa) != 0)
{
return -1;
}
// 创建UDP套接字
m_UDPSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(INVALID_SOCKET == m_UDPSocket)
{
return -2;
}
SOCKADDR_IN localAddr;
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(localPort);
localAddr.sin_addr.s_addr=INADDR_ANY;
// 绑定地址
if(bind(m_UDPSocket,(sockaddr*)&localAddr,sizeof(localAddr)) != 0)
{
return -3;
}
// 设置非堵塞通讯
DWORD wCmdParam = 1;
ioctlsocket(m_UDPSocket,FIONBIO,&wCmdParam);
// 创建一个线程退出事件
m_ExitThreadEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
};
展开阅读全文