我将用VC/MFC编写一套实时交易系统的客户端软件,它必须通过TCP和UDP协议直接和交易主机通信。
请教如何用VC/MFC实现对TCP和UDP协议的直接操作?要增加哪些MFC模块?怎样收发信息?怎样拆解TCP数据包头和信息正文?对TCP和UDP协议的操作有何区别?
请详细为我解释一下技术细节,有sample代码更好。我将感激不尽并大把送分!
请教如何用VC/MFC实现对TCP和UDP协议的直接操作?要增加哪些MFC模块?怎样收发信息?怎样拆解TCP数据包头和信息正文?对TCP和UDP协议的操作有何区别?
请详细为我解释一下技术细节,有sample代码更好。我将感激不尽并大把送分!
解决方案 »
- CWinApp::InitInstance调用SetRegistryKey函数,这个函数并没有指定注册表信息的路径啊!
- png 图片如何灰度化
- HANDLE handle;其中的HDANDLE指的是什么
- CHtmlEditView在有些时候会无法输入,可能是哪些原因造成的。
- 问一下这条语句是什么意思?
- 请问如何在内存中生成一个文件?
- 请教各位大哥: 在WIN32 SDK中怎样实现excel里的条状控件?
- :-)大家祝我一路顺风吧!!!
- (“在线等待”)--要用A2W,T2COLE等,要包括什么头文件?
- vc++ 组合框怎么使用 有截图更好
- 请教bitblt
- 特急!!!我的程序在debug下运行正常,但在release下却宕掉,谁能告诉我
// CustomIPPackageCtl.cpp: implementation of the CCustomIPPackageCtl class.
//
//////////////////////////////////////////////////////////////////////#include "stdafx.h"
#include "udpdemo.h"
#include "CustomIPPackageCtl.h"
#include <mstcpip.h>
#include <Ws2tcpip.h> #ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////CCustomIPPackageCtl::CCustomIPPackageCtl()
{
s = INVALID_SOCKET;
}CCustomIPPackageCtl::~CCustomIPPackageCtl()
{}BOOL CCustomIPPackageCtl::init()
{
ASSERT(s == INVALID_SOCKET);
TCHAR szErr[MAX_PATH];
DWORD dwErr;
int timeout = 1000;
BOOL flag = TRUE;
s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if (s == INVALID_SOCKET)
{
goto _RESULT_ERR_LABEL;
}
// Set timeout
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)) == SOCKET_ERROR)
{
goto _RESULT_ERR_LABEL;
}
// 设置IP_HDRINCL以自己填充IP首部
if (setsockopt(s,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(int)) == SOCKET_ERROR)
{
goto _RESULT_ERR_LABEL;
}
return TRUE;
_RESULT_ERR_LABEL:
dwErr = WSAGetLastError();
sprintf(szErr, "Error == %ld ", dwErr);
AfxMessageBox(szErr);
closesocket(s);
s = INVALID_SOCKET;
return FALSE;
}void CCustomIPPackageCtl::destroy()
{
closesocket(s);
}// CheckSum: 计算校验和的子函数
USHORT checksum(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);
} BOOL CCustomIPPackageCtl::SendUDPPackage(const char *srcIP,
const char *dstIP,
USHORT srcPort,
USHORT dstPort,
const char *data,
USHORT dataLen)
{
char* buff = new char[U_MAXLEN];
UPSDHEADER phd;
phd.saddr = inet_addr(srcIP);
phd.daddr = inet_addr(dstIP);
phd.mbz = 0;
phd.ptcl = IPPROTO_UDP;
phd.udpl = htons(U_HLEN + dataLen);
UDP udp_hd;
udp_hd.u_src = htons(srcPort);
udp_hd.u_dst = htons(dstPort);
udp_hd.u_len = htons(U_HLEN + dataLen);
udp_hd.u_cksum = 0;
memcpy(udp_hd.u_data, data, dataLen); int size = sizeof(UPSDHEADER) + U_HLEN + dataLen;
ASSERT(size < U_MAXLEN); // the size less than the maximal UDP package size // Calculate UDP partition's checksum
memset(buff, 0, U_MAXLEN);
memcpy(buff, &phd, sizeof(UPSDHEADER));
memcpy(buff + sizeof(UPSDHEADER), &udp_hd, U_HLEN);
memcpy(buff + sizeof(UPSDHEADER) + U_HLEN, udp_hd.u_data, dataLen);
udp_hd.u_cksum = checksum((USHORT*)buff, size); IP ip_hd;
ip_hd.ip_verlen = (4 << 4 | 20 / sizeof(unsigned long));
ip_hd.ip_tos = 0;
ip_hd.ip_len = htons(IP_HLEN_REF(ip_hd) + U_HLEN + dataLen);
ip_hd.ip_id = 0;
ip_hd.ip_fragoff = 0;
ip_hd.ip_ttl = 128;
ip_hd.ip_proto = IPPROTO_UDP;
ip_hd.ip_cksum = 0;
ip_hd.ip_src = phd.saddr;
ip_hd.ip_dst = phd.daddr;
// Calculate IP partition's checksum /*
size = IP_HLEN_REF(ip_hd) + U_HLEN;
ASSERT(size < U_MAXLEN); // the size less than the maximal UDP package size
memset(buff, 0, U_MAXLEN); memcpy(buff, &ip_hd, IP_HLEN_REF(ip_hd));
memcpy(buff + IP_HLEN_REF(ip_hd), &udp_hd, U_HLEN); ip_hd.ip_cksum = checksum((USHORT*)buff, size);
*/ // Send data
size = IP_HLEN_REF(ip_hd) + U_HLEN + dataLen;
ASSERT(size < U_MAXLEN); // the size less than the maximal UDP package size
memset(buff, 0, U_MAXLEN); memcpy(buff, &ip_hd, IP_HLEN_REF(ip_hd));
memcpy(buff + IP_HLEN_REF(ip_hd), &udp_hd, U_HLEN);
memcpy(buff + IP_HLEN_REF(ip_hd) + U_HLEN, data, dataLen);
SOCKADDR_IN toAddr;
toAddr.sin_family = AF_INET;
toAddr.sin_addr.s_addr = ip_hd.ip_dst;
toAddr.sin_port = udp_hd.u_dst;
/*
45 00
00 20 65 6D 00 00 80 11 1C 53 C0 A8 01 F5 CA 65
2C 0A
1F 40 1F 40 00 0C 20 6F
74 65 73 74
*/
/*
unsigned char realData[] = {
0x45, 0x00, 0x00, 0x20, 0x65, 0x6d, 0x00, 0x00,
0x80, 0x11, 0x1c, 0x53, 0xc0, 0xa8, 0x01, 0xf5,
0xca, 0x65, 0x2c, 0x0a, 0x1f, 0x40, 0x1f, 0x40,
0x00, 0x0c, 0x20, 0x6f, 0x74, 0x65, 0x73, 0x74
};
*/ int ret = sendto(s, buff, size, 0, (const sockaddr*)&toAddr, sizeof(toAddr)); /*
int ret = sendto(s,
(const char*)realData,
sizeof(realData), 0,
(const sockaddr*)&toAddr,
sizeof(toAddr));
*/
if (ret == SOCKET_ERROR)
{
DWORD dwErr = ::WSAGetLastError();
}
delete buff; return ret != SOCKET_ERROR;
}
我来读一下加点注释;
1、用UDP协议通讯,存在一个无连接问题;你可以填充包头的方法保证传输的可靠
2、数据包都有自己特定的格式的,如果你要改变它的组成,使用SETSOCKOPT的方法;
3、由于数据通讯的完整程度高采用CRC校验,CHECKSUM函数;
4、后面的就是发送接收了
raw socket can capture :tcp +ip +data
winpcap can capture : mac +tcp+ip +data
一般的这种东西变是普通的CSOCKET类就足以应付了吧,我想,
如果你不想用CSOCKET的话,你可以封装一个MYSOCKET来用的。
我想你是不必要用到RAWSOCKET的,
因为好像只有那些比较低级的系统级的才会用到(比如发一个ARP啦,ICMP信息包啦之类的或是实现一些高级功能)SOCK函数会帮你把收到的放到缓冲区中的不用你折了。