cpp文件
// scanDlg.cpp : implementation file
//
#include "stdafx.h"
#include "scan.h"
#include "scanDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CscanDlg dialog
CscanDlg::CscanDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CscanDlg::IDD, pParent)
, m_star_port(_T(""))
, m_end_port(_T(""))
, m_IP(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CscanDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST1, m_list);
DDX_Text(pDX, IDC_EDIT2, m_star_port);
DDX_Text(pDX, IDC_EDIT3, m_end_port);
DDX_Text(pDX, IDC_EDIT1, m_IP);
}
BEGIN_MESSAGE_MAP(CscanDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CscanDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
// CscanDlg message handlers
BOOL CscanDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 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)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
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
return TRUE; // return TRUE unless you set the focus to a control
}
hostent* CscanDlg::g_pHost = 0;
SOCKET CscanDlg::sock = 0;
void CscanDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::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 CscanDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CscanDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
void CscanDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
send_revc((LPSTR)(LPCTSTR)m_IP,(LPSTR)(LPCTSTR)m_star_port,(LPSTR)(LPCTSTR)m_end_port,&m_list);//char ch1[],char tr1[],char tr2[]
}
void CscanDlg ::send_revc(char ch1[],char tr1[],char tr2[],CListBox* m_list)
{
WSADATA WSAData;
WSAStartup(MAKEWORD(2,2), &WSAData);
sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED);//定義套接字
BOOL flag = true;
setsockopt(sock,IPPROTO_IP, IP_HDRINCL,(char )&flag,sizeof(flag));
char sLocalName[64];
gethostname((char)sLocalName, sizeof(sLocalName)-1);
g_pHost = gethostbyname(sLocalName);
sockaddr_in addr_local;
addr_local.sin_addr = *(in_addr *)g_pHost->h_addr_list[0]; //綁定到本地網卡,INADDR_ANY不行
addr_local.sin_family = AF_INET;//
addr_local.sin_port = htons(SOURCE_PORT);
bind(sock, (PSOCKADDR)&addr_local, sizeof(sockaddr_in));//綁套接字
DWORD dwValue = 1;
SADDR sAddr;
USHORT int1,int2;
sAddr.m_destip=ch1;
sAddr.m_starpost=atoi(tr1);
sAddr.m_endpost=atoi(tr2);
ioctlsocket(sock, SIO_RCVALL, &dwValue);
int nTimeOut = 500;//設置超時
setsockopt(sock,SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOut, sizeof(nTimeOut));
HANDLE threads[2];//開雙線程
threads[0] = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)revcfunc,(LPVOID)m_list,0,NULL);
threads[1] = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)sendfunc,(LPVOID)(&sAddr), 0,NULL);
WaitForMultipleObjects(2,threads,FALSE,INFINITE);
}
USHORT CscanDlg ::checksumfunc(USHORT buffer, int size)//檢驗和函數
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size)
{
cksum += *(UCHAR)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}
void CscanDlg ::sendfunc(SADDR* sAddr )
{
IP_HEADER ipHeader;
TCP_HEADER tcpHeader;
PSD_HEADER psdHeader;
char Sendto_Buff[MAX_BUFF_LEN]; //發送緩沖區
unsigned short check_Buff[MAX_BUFF_LEN]; //檢驗和緩沖區
const char tcp_send_data[]={"This is my homework of networt,I am happy!"};
BOOL flag;
int rect,nTimeOver;
//先試一下在外面弄好套接字初始化行不行
flag=true;
nTimeOver=1000;
//填充IP首部
ipHeader.h_verlen=(IPVER<<4 | sizeof(ipHeader)/sizeof(unsigned long));
ipHeader.tos=(UCHAR)0;
ipHeader.total_len=htons((unsigned short)sizeof(ipHeader)+sizeof(tcpHeader)+sizeof(tcp_send_data));
ipHeader.ident=0; //16位標識
ipHeader.frag_and_flags=0; //3位標志位
ipHeader.ttl=128; //8位生存時間
ipHeader.proto=IPPROTO_UDP; //協議類型
ipHeader.checksum=0; //檢驗和暫時為0
ipHeader.sourceIP=*(int*)g_pHost->h_addr_list[0]; //32位源IP地址可以直接獲取
ipHeader.destIP=inet_addr(sAddr->m_destip); //32位目的IP地址
//計算IP頭部檢驗和
memset(check_Buff,0,MAX_BUFF_LEN);
memcpy(check_Buff,&ipHeader,sizeof(IP_HEADER));
ipHeader.checksum=checksumfunc(check_Buff,sizeof(IP_HEADER));
//構造TCP偽首部
psdHeader.saddr=ipHeader.sourceIP;
psdHeader.daddr=ipHeader.destIP;
psdHeader.mbz=0;
psdHeader.ptcl=ipHeader.proto;
psdHeader.tcpl=htons(sizeof(TCP_HEADER)+sizeof(tcp_send_data));
for(int i=sAddr->m_starpost;i<sAddr->m_endpost;i++)
//填充TCP首部
{
tcpHeader.th_dport=htons(i); //16位目的端口號
tcpHeader.th_sport=htons(SOURCE_PORT); //16位源端口號
tcpHeader.th_seq=0; //SYN序列號
tcpHeader.th_ack=0; //ACK序列號置為0
//TCP長度和保留位
tcpHeader.th_lenres=(sizeof(tcpHeader)/sizeof(unsigned long)<<4|0);
tcpHeader.th_flag=1; //修改這裡來實現不同的標志位探測,2是SYN,1是//FIN,16是ACK探測 等等
tcpHeader.th_win=htons((unsigned short)16384); //窗口大小
tcpHeader.th_urp=0; //偏移大小
tcpHeader.th_sum=0; //檢驗和暫時填為0
//計算TCP校驗和
memset(check_Buff,0,MAX_BUFF_LEN);
memcpy(check_Buff,&psdHeader,sizeof(psdHeader));
memcpy(check_Buff+sizeof(psdHeader),&tcpHeader,sizeof(tcpHeader));
memcpy(check_Buff+sizeof(PSD_HEADER)+sizeof(TCP_HEADER),
tcp_send_data,sizeof(tcp_send_data));
tcpHeader.th_sum=checksumfunc(check_Buff,sizeof(PSD_HEADER)+
sizeof(TCP_HEADER)+sizeof(tcp_send_data));
//填充發送緩沖區
memset(Sendto_Buff,0,MAX_BUFF_LEN);
memcpy(Sendto_Buff,&ipHeader,sizeof(IP_HEADER));
memcpy(Sendto_Buff+sizeof(IP_HEADER),&tcpHeader,
sizeof(TCP_HEADER));
memcpy(Sendto_Buff+sizeof(IP_HEADER)+sizeof(TCP_HEADER),
tcp_send_data,sizeof(tcp_send_data));
int datasize=sizeof(IP_HEADER)+sizeof(TCP_HEADER)+
sizeof(tcp_send_data);
//發送數據報的目的地址
SOCKADDR_IN dest;
memset(&dest,0,sizeof(dest));
dest.sin_family=AF_INET;
dest.sin_addr.s_addr=inet_addr(sAddr->m_destip);
dest.sin_port=htons(i);
rect=sendto(sock,Sendto_Buff,datasize, 0,(struct sockaddr*)&dest, sizeof(dest));
}
}
void CscanDlg ::revcfunc(CListBox* m_list)
{
CString str;
char RecvBuf[MAX_BUFF_LEN];
IP_HEADER* ip;
TCP_HEADER* tcp;
while(1)
{
int ret = recv(sock, RecvBuf, MAX_BUFF_LEN, 0);
if (ret > 0)
{
ip = (IP_HEADER*)RecvBuf;
tcp = (TCP_HEADER*)(RecvBuf + (ip->h_verlen&0x0f)*4);
str.Format(_T("%hu"), tcp->th_sport);
m_list->AddString(str);
}
else str.Format(_T("%d"),ret),m_list->AddString(str);
}
}
頭文件// scanDlg.h : header file
//
#pragma once
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
//#define SIO_RCVALL_WSAIOW(IOC_VENDOR,1)
#include
#include
#include
#include "afxwin.h"
#define IPVER 4 //IP協議預定
#define MAX_BUFF_LEN 65500 //發送緩沖區最大值
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define SOURCE_PORT 8088 //local TCP segment source port
// CscanDlg dialog
class CscanDlg : public CDialogEx
{
// Construction
public:
CscanDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_SCAN_DIALOG };
typedef struct ip_hdr //定義IP首部
{
UCHAR h_verlen; //4位首部長度,4位IP版本號
UCHAR tos; //8位服務類型TOS
USHORT total_len; //16位總長度(字節)
USHORT ident; //16位標識
USHORT frag_and_flags; //3位標志位
UCHAR ttl; //8位生存時間 TTL
UCHAR proto; //8位協議 (TCP, UDP 或其他)
USHORT checksum; //16位IP首部校驗和
ULONG sourceIP; //32位源IP地址
ULONG destIP; //32位目的IP地址
}IP_HEADER;
typedef struct tsd_hdr //定義TCP偽首部
{
ULONG saddr; //源地址
ULONG daddr; //目的地址
UCHAR mbz; //沒用
UCHAR ptcl; //協議類型
USHORT tcpl; //TCP長度
}PSD_HEADER;
typedef struct tcp_hdr //定義TCP首部
{
USHORT th_sport; //16位源端口
USHORT th_dport; //16位目的端口
ULONG th_seq; //32位序列號
ULONG th_ack; //32位確認號
UCHAR th_lenres; //4位首部長度/6位保留字
UCHAR th_flag; //6位標志位
USHORT th_win; //16位窗口大小
USHORT th_sum; //16位校驗和
USHORT th_urp; //16位緊急數據偏移量
}TCP_HEADER;
typedef struct SADDR //定義TCP首部
{
char* m_destip;
USHORT m_starpost;
USHORT m_endpost;
};
USHORT static checksumfunc(USHORT buffer, int size);
void static sendfunc(SADDR sAddr);
void static revcfunc(CListBox* m_list);
void send_revc(char ch1[],char tr1[],char tr2[],CListBox* m_list);
SOCKET static sock; //用於收發TCP報文段的全局socket
hostent static *g_pHost;
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CListBox m_list;
afx_msg void OnBnClickedButton1();
CString m_star_port;
CString m_end_port;
CString m_IP;
};
OnBnClickedButton1中的調用阻塞了消息循環。把send_revc中的waitForMultiObjects函數去掉吧,可以使用afxbeginthread()開啟線程,並設置CWinThread類的成員變量m_bAutoDelete為TRUE。或者設置等待窗口,等待線程完成。反正WaitForMuliObjects阻塞了消息循環,所以在revc線程中添加ListBox條目會被阻塞。