如何用VC/MFC实现对TCP和UDP协议的直接操作?

eniac2003 2003-05-14 11:34:44
我将用VC/MFC编写一套实时交易系统的客户端软件,它必须通过TCP和UDP协议直接和交易主机通信。
请教如何用VC/MFC实现对TCP和UDP协议的直接操作?要增加哪些MFC模块?怎样收发信息?怎样拆解TCP数据包头和信息正文?对TCP和UDP协议的操作有何区别?
请详细为我解释一下技术细节,有sample代码更好。我将感激不尽并大把送分!
...全文
206 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Rayanywhere 2003-05-17
  • 打赏
  • 举报
回复
想做底层socket? 去下载winpcap把
kingzai 2003-05-17
  • 打赏
  • 举报
回复
if you want to deal with ip package,analyse tcp header or udp header,you can use raw socket or winpcap.
raw socket can capture :tcp +ip +data
winpcap can capture : mac +tcp+ip +data

jwyhit 2003-05-17
  • 打赏
  • 举报
回复
楼上两位说的够好,收藏!
sevencat 2003-05-17
  • 打赏
  • 举报
回复
不是很清楚你到底想要的是东西,
一般的这种东西变是普通的CSOCKET类就足以应付了吧,我想,
如果你不想用CSOCKET的话,你可以封装一个MYSOCKET来用的。
我想你是不必要用到RAWSOCKET的,
因为好像只有那些比较低级的系统级的才会用到(比如发一个ARP啦,ICMP信息包啦之类的或是实现一些高级功能)

SOCK函数会帮你把收到的放到缓冲区中的不用你折了。
cauiot 2003-05-17
  • 打赏
  • 举报
回复
太好了,收藏!
chenyc 2003-05-15
  • 打赏
  • 举报
回复
楼上兄弟写的好:
我来读一下加点注释;
1、用UDP协议通讯,存在一个无连接问题;你可以填充包头的方法保证传输的可靠
2、数据包都有自己特定的格式的,如果你要改变它的组成,使用SETSOCKOPT的方法;
3、由于数据通讯的完整程度高采用CRC校验,CHECKSUM函数;
4、后面的就是发送接收了
windows_editor 2003-05-15
  • 打赏
  • 举报
回复
给你一段代码 UDP的直接封装报头发送
// 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;
}
tserpent 2003-05-15
  • 打赏
  • 举报
回复
这是很一般的问题。可以从 www.vckbase.com www.codeguru.com www.codeproject.com 到处都有很多源码。

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧