//#include "pch.h"
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include<string>
#pragma comment(lib,"ws2_32.lib")
# define LOCALPORT 5555
#define PEERPORT 1235
#define PEERIP "192.168.43.41"
#define BUFFER_LEN 1000
using namespace std;
typedef struct _IPHeader // 定义IP首部结构
{
unsigned char iphVerLen; // 版本号和头长度各占4位
unsigned char ipTOS; // 服务类型
unsigned short ipLength; // 分组总长度
unsigned short ipID; //分组标识,惟一标识发送的每一个数据报
unsigned short ipFlags; // 标志
unsigned char ipTTL; // 生存时间,TTL
unsigned char ipProtocol; // 协议可以是TCP、UDP、ICMP等
unsigned short ipChecksum; // 校验和
unsigned long ipSource; // 源IP地址
unsigned long ipDestination; // 目的IP地址
} IPHeader;
typedef struct _UDPHeader //定义UDP首部结构
{
unsigned short sourcePort; // 源端口号
unsigned short destinationPort;// 目的端口号
unsigned short len; // 包长度
unsigned short checksum; // 校验和
} UDPHeader;
typedef struct tsd_hdr //定义UDP伪首部结构
{
unsigned long saddr; //源IP地址
unsigned long daddr; //目的IP地址
char mbz; //填充
char ptcl; //协议型
unsigned short udpl; //TCP长度
}PSDHEADER;
/********CheckSum:计算校验和的函数***************/
unsigned short checksum(unsigned short *buffer, int size)
{
unsigned long cksum = 0;
while (size > 1)
{
cksum += *buffer++;
size -= sizeof(unsigned short);
}
if (size)
{
cksum += *(char *)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (unsigned short)(~cksum);
}
struct sockaddr_in peeraddr, localaddr;
int len = sizeof(struct sockaddr_in);
WSAEVENT bExit;
DWORD WINAPI RecvMessage(LPVOID parsock) {
SOCKET recvsock = (SOCKET)parsock;
int err;
while (TRUE)
{
char recvBuffer[BUFFER_LEN];
memset(recvBuffer, 0, BUFFER_LEN);
if (recvfrom(recvsock, recvBuffer, sizeof(recvBuffer), 0, NULL, NULL) != SOCKET_ERROR) {
cout << endl;
cout << inet_ntoa(peeraddr.sin_addr) << ":";
//cout << inet_ntoa(peeraddr.sin_addr) << ":" << recvBuffer << endl;
for (int i = 28; i < 49; i++)
{
printf("%c", recvBuffer[i]);
}
/*for (int i = 0; i < BUFFER_LEN; i++)
{
printf("%c", recvBuffer[i]);
}*/
cout << endl;
if (recvBuffer[28] == 'b'&&recvBuffer[29] == 'y'&&recvBuffer[30] == 'e'){
SetEvent(bExit);
break;
}
/*if (strcmp(recvBuffer, "bye") == 0) {
SetEvent(bExit); break;
}*/
}
else {
err = WSAGetLastError();
if (err == WSAECONNRESET) { cout << "The peer is closed\n"; continue; }
//cout << "recive error" << err << endl;
SetEvent(bExit); break;
}
}
return 0;
}
DWORD WINAPI SendMessage(LPVOID parsock) {
/*SOCKET sendsock = (SOCKET)parsock;
char sendBuffer[BUFFER_LEN];
while (true){
cout << "输入要发送的信息:" << endl;
cin.getline(sendBuffer, sizeof(sendBuffer));
sendto(sendsock, sendBuffer, strlen(sendBuffer) + 1, 0, (struct sockaddr*)&peeraddr, len);
if (strcmp(sendBuffer, "bye") == 0){
SetEvent(bExit);
break;
}
}
return 0;*/
char szDestIp[] = "192.168.43.41";// 目的IP地址
char szSourceIp[] = "192.168.43.232";//源IP地址,必须是本机IP地址
/* cout << "输入本机地址:" << endl;
cin.getline(szSourceIp, sizeof(szSourceIp));
cout << "输入目的地址:" << endl;
cin.getline(szDestIp, sizeof(szDestIp));*/
char szMsg[1000];
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
{
cout << "WSAStartup Error!\n";
return false;
}
/*** 创建原始套接字***/
SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
while (TRUE)
{
cout << "输入要发送的信息:" ;
cin.getline(szMsg, sizeof(szMsg));
//cin.ignore();
int nMsgLen = strlen(szMsg);
/***设置IP_HDRINCL选项***/
int bIncl = 1;
setsockopt(sRaw, IPPROTO_IP, IP_HDRINCL, (char *)&bIncl, sizeof(bIncl));
/****创建并填充IP头****/
char buff[1024] = { 0 };//存放自定义IP分组的存储区
//填充IP分组首部
IPHeader *pIphdr = (IPHeader *)buff;
pIphdr->iphVerLen = (4 << 4 | (sizeof(IPHeader) / sizeof(unsigned long))); //版本与长度
pIphdr->ipLength = htons(sizeof(IPHeader) + sizeof(UDPHeader) + nMsgLen);//分组长度
pIphdr->ipTTL = 128; //生存时间
pIphdr->ipProtocol = IPPROTO_UDP;//协议为UDP
pIphdr->ipSource = inet_addr(szSourceIp); //源IP地址
pIphdr->ipDestination = inet_addr(szDestIp); //目的IP地址
pIphdr->ipChecksum = checksum((unsigned short*)pIphdr, sizeof(IPHeader)); //校验和
/**** 填充UDP首部***/
UDPHeader *pUdphdr = (UDPHeader *)&buff[sizeof(IPHeader)];
pUdphdr->sourcePort = htons(LOCALPORT); //源端口
pUdphdr->destinationPort = htons(PEERPORT);//目的端口
pUdphdr->len = htons(sizeof(UDPHeader) + nMsgLen);//报头长度¨
pUdphdr->checksum = 0; //校验和
/***填充UDP数据****/
char *pData = &buff[sizeof(IPHeader) + sizeof(UDPHeader)];
memcpy(pData, szMsg, nMsgLen);
/****计算UDP校验和***/
PSDHEADER psdHeader;//构造伪首部
psdHeader.saddr = pIphdr->ipSource;
psdHeader.daddr = pIphdr->ipDestination;
psdHeader.mbz = 0;
psdHeader.ptcl = IPPROTO_UDP;
psdHeader.udpl = htons(sizeof(UDPHeader) + nMsgLen);
char szBuff[1024];
memcpy(szBuff, &psdHeader, sizeof(psdHeader));
memcpy(szBuff + sizeof(psdHeader), pUdphdr, sizeof(UDPHeader));
memcpy(szBuff + sizeof(psdHeader) + sizeof(UDPHeader), pData, nMsgLen);
pUdphdr->checksum = checksum((unsigned short *)szBuff,
sizeof(psdHeader) + sizeof(UDPHeader) + nMsgLen);
/*** 设置目的地址***/
SOCKADDR_IN destAddr = { 0 };
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(PEERPORT);
destAddr.sin_addr.S_un.S_addr = inet_addr(szDestIp);
/***发送原始UDP数据报***/
int nRet;
nRet = sendto(sRaw, buff, sizeof(IPHeader) + sizeof(UDPHeader) + nMsgLen, 0, (sockaddr*)&destAddr, sizeof(destAddr));
if (strcmp(szMsg, "bye") == 0) {
SetEvent(bExit); break;
}
if (nRet == SOCKET_ERROR)
{
cout << " 发送错误,错误码:" << WSAGetLastError() << endl;
break;
}
/*else
cout << "发送字节数:" << nRet << endl;*/
Sleep(1000);
}
/***结束处理***/
closesocket(sRaw);
WSACleanup();
return 0;
}
int main(int argc, char *argv[]) {
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
cout << "没有合适的winsock.dll\n";
return 0;
}
bExit = WSACreateEvent();
SOCKET udpsocket;
//udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
udpsocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(LOCALPORT);
localaddr.sin_addr.s_addr = inet_addr("192.168.43.232");
//bind(udpsocket, (struct sockaddr*)&localaddr, len);
int Bind = bind(udpsocket, (struct sockaddr*)&localaddr, len);
if (Bind == SOCKET_ERROR) {
cout << "地址绑定失败!" << endl;
WSACleanup();
return 0;
}
peeraddr.sin_family = AF_INET;
peeraddr.sin_port = htons(PEERPORT);
peeraddr.sin_addr.s_addr = inet_addr(PEERIP);
HANDLE hThrdsnd, hThrdrcv;
DWORD nThrdsnd, nThrdrcv;
hThrdrcv = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RecvMessage, (LPVOID)udpsocket, 0, &nThrdrcv);
hThrdsnd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendMessage, (LPVOID)udpsocket, 0, &nThrdsnd);
// hThrdrcv = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RecvMessage, (LPVOID)udpsocket, 0, &nThrdrcv);
WaitForSingleObject(bExit, INFINITE);
closesocket(udpsocket);
WSACleanup();
system("pause");
return 0;
}