我将用VC/MFC编写一套实时交易系统的客户端软件,它必须通过TCP和UDP协议直接和交易主机通信。
请教如何用VC/MFC实现对TCP和UDP协议的直接操作?要增加哪些MFC模块?怎样收发信息?怎样拆解TCP数据包头和信息正文?对TCP和UDP协议的操作有何区别?
请详细为我解释一下技术细节,有sample代码更好。我将感激不尽并大把送分!

解决方案 »

  1.   

    这是很一般的问题。可以从 www.vckbase.com www.codeguru.com www.codeproject.com 到处都有很多源码。
      

  2.   

    给你一段代码 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;
    }
      

  3.   

    楼上兄弟写的好:
        我来读一下加点注释;
        1、用UDP协议通讯,存在一个无连接问题;你可以填充包头的方法保证传输的可靠
        2、数据包都有自己特定的格式的,如果你要改变它的组成,使用SETSOCKOPT的方法;
        3、由于数据通讯的完整程度高采用CRC校验,CHECKSUM函数;
        4、后面的就是发送接收了
      

  4.   

    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
      

  5.   

    不是很清楚你到底想要的是东西,
    一般的这种东西变是普通的CSOCKET类就足以应付了吧,我想,
    如果你不想用CSOCKET的话,你可以封装一个MYSOCKET来用的。
    我想你是不必要用到RAWSOCKET的,
    因为好像只有那些比较低级的系统级的才会用到(比如发一个ARP啦,ICMP信息包啦之类的或是实现一些高级功能)SOCK函数会帮你把收到的放到缓冲区中的不用你折了。
      

  6.   

    想做底层socket?  去下载winpcap把