代码段中TRACE是调试的时候使用的删掉对代码没有影响,只是在写代码过程中方便查看结果和调试。首先填充的是SOCKADDR_IN结构体,该结构体包换了IP地址、端口号、地址簇等信息。都要进行填充。同时要注意的网络字节和本机字节的转换。使用WSASocket创建套接字,
SOCKET WSAAPI WSASocket ( int af, int type, int protocol,LPPROTOCOL_INFO lpProtocolInfo, Group g, int iFlags);
af:地址族描述。目前仅支持AF_INET格式,亦即ARPA Internet地址格式。
type:新套接口的类型描述。
protocol:套接口使用的特定协议,如果调用者不愿指定协议则定为0。
lpProtocolInfo:一个指向PROTOCOL_INFO结构的指针,该结构定义所创建套接口的特性。如果本参数非零,则前三个参数(af, type, protocol)被忽略。
g:套接口组的描述字。
iFlags:套接口属性描述。
通过使用setsockopt()设置时候亲自对IP头进行处理。
int PASCAL FAR setsockopt( SOCKET s, int level, intoptname,const char FAR *optval, int optlen);
s:标识一个套接口的描述字。
level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。
optname:需设置的选项。
optval:指针,指向存放选项值的缓冲区。
optlen:optval缓冲区长度。
使用Bind将套接字和ip、端口绑定到一起
在无限循环中,使用recv接收数据,recv(Sniffsock,buff,sizeof(buf),0);
将buf转化为转化为ip结构,然后对ip结构中数据处理,使用sprintf_s()对数据进行格式化,转化成char*,然后使用CListCtrl的SetItemText将数据打印上相应的子项目中。
运行结果:
网络环境的初始化: 首先,第一点就是对网络环境的初始化。在MFC中一般是在程序初始化中InitInstance中进行的。 在头文件包含#include 在InitInstance()中调用 WORD wVersionRequested; LOBYTE和HTBYTE宏对DWORD进行操作取得器版本号信息,MAKEWORD()可知道将两个BYTE合并成一个WORD 注意不要要忘了在退出时重载ExitInstance调用WSACleanup();关闭。 一旦一个应用程序或者DLL调用WSAStartup成功,他可以执行其他需要的WindowsSockets 调用,当要结束使用Winsock.dll服务,必须调用WSACleanup来释放应用程序使用Winsock.dll的资源。 2第一步中基本完成了对网络环境的初始化,然后对界面进行初始化,程序是个对话框程序,在程序中OnInitDialog()中对程序的界面初始化,Dialog中包含一个CListCtrl、一个IPAddressCtrl、两个button按钮的简单界面。同时将获取本机IP也在此初始化。 char name[255]; 使用GetDlgItem()获得ID的对象指针(注意转化类型)。 取得本地ip,gethostname取得本机名,然后通过gethostbyname根据本机名取得IP。并且保存在HOSTENT(hostentry)的结构体中。 struct hostent { char *h_name;//地址的正式名字 char **h_aliases; //空字节,地址的预备名的指针 int h_addrtype; //地址类型,一般为AF_INET int h_length; //地址的比特长度 char **h_addr_list;//主机的网络地址指针,注意这是网络字节序通过inet_ntoa()转化成ascii字节序,返回char*; }; #define h_addr h_addr_list[0] 通过CIPAdressCtrl的setwindowtext()将char*字符串设置到IP控件中。 CListCtrl的成员函数声明 DWORD SetExtendedStyle(DWORD dwNewStyle ); 使用InsertColumn()创建行用InsertItem();创建列,setitemtext()设置子项文本,界面初始化完毕。 3.实现按钮的拦截包功能 需要设置一个线程专门进行拦截包处理,因为如果主线程进行拦截包的话会是界面无法响应,因为主线程阻塞。但是要考虑到的是将线程函数设置为静态函数或者全局函数,因为如果你把线程处理函数设置成成员函数的话,会隐含的传入this参数,会使编译器报错。可是屏蔽了this指针问题又来了。线程函数里面要处理和使用对话框对象的成员数据和成员函数。我们可以知道线程函数可以传入一个LPVOID参数,所以将this指针作为参数传给线程函数,这样就两个问题都解决了。同时为了简单的思想线程的启动和关闭,使用了一个bool类型的变量,根据变量来控制线程的启动和停止。代码如下: void { } UINT { WSAIoctl(SinfferSock,SIO_RCVALL,&dwBufferInLen,sizeof(dwBufferInLen),&dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL); } 代码段中TRACE是调试的时候使用的删掉对代码没有影响,只是在写代码过程中方便查看结果和调试。首先填充的是SOCKADDR_IN结构体,该结构体包换了IP地址、端口号、地址簇等信息。都要进行填充。同时要注意的网络字节和本机字节的转换。使用WSASocket创建套接字, SOCKET WSAAPI WSASocket ( int af, int type, int protocol,LPPROTOCOL_INFO lpProtocolInfo, Group g, int iFlags); af:地址族描述。目前仅支持AF_INET格式,亦即ARPA Internet地址格式。 type:新套接口的类型描述。 protocol:套接口使用的特定协议,如果调用者不愿指定协议则定为0。 lpProtocolInfo:一个指向PROTOCOL_INFO结构的指针,该结构定义所创建套接口的特性。如果本参数非零,则前三个参数(af, type, protocol)被忽略。 g:套接口组的描述字。 iFlags:套接口属性描述。 通过使用setsockopt()设置时候亲自对IP头进行处理。 int PASCAL FAR setsockopt( SOCKET s, int level, intoptname,const char FAR *optval, int optlen); s:标识一个套接口的描述字。 level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。 optname:需设置的选项。 optval:指针,指向存放选项值的缓冲区。 optlen:optval缓冲区长度。 使用Bind将套接字和ip、端口绑定到一起 在无限循环中,使用recv接收数据,recv(Sniffsock,buff,sizeof(buf),0); 将buf转化为转化为ip结构,然后对ip结构中数据处理,使用sprintf_s()对数据进行格式化,转化成char*,然后使用CListCtrl的SetItemText将数据打印上相应的子项目中。 运行结果: |
联系客服