⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp.cpp

📁 使用VC++开发的很棒的上网拨号工具的程序的源码,可以选择PING,UDP,TCP/IP等等方式,功能比较全面.Using Visual C + + development of the great
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Tcp.cpp: implementation of the CTcp class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "demo.h"
#include "Tcp.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTcp::CTcp()
{

}

CTcp::~CTcp()
{

}

/*
 * Initialize the tcp implementation
 */
void CTcp::tcp_Init()
{
    //extern eth_HwAddress sed_lclEthAddr;

    /* initialize ethernet interface */
    //sed_Init();

    tcp_allsocs = NIL;
#ifdef DEBUG
    tcp_logState = 0;
#endif
    tcp_id = 0;

    /* hack - assume the network number */
//    sin_lclINAddr = ;//本机IP地址
}

/*
 * Actively open a TCP connection to a particular destination.
 */
void CTcp::tcp_Open(tcp_Socket *s,word lport,in_HwAddress ina,word port,procref datahandler)
{
    //extern eth_HwAddress sed_ethBcastAddr;//以太网广播地址

    s->state = tcp_StateSYNSENT;
    s->timeout = tcp_LONGTIMEOUT;
    //if ( lport == 0 ) lport = clock_ValueRough();
    s->myport = lport;
    /*if ( ! sar_MapIn2Eth(ina, &s->hisethaddr[0]) ) {//地址解析
        printf("tcp_Open of 0x%x: defaulting ethernet address to broadcast\n", ina);
        Move(&sed_ethBcastAddr[0], &s->hisethaddr[0], sizeof(eth_HwAddress));
    }*/
    s->hisaddr = ina;
    s->hisport = port;
    s->seqnum = 0;
    s->dataSize = 0;
    s->flags = tcp_FlagSYN;
    s->unhappy = true;
    s->dataHandler = datahandler;
    s->next = tcp_allsocs;
    tcp_allsocs = s;
    tcp_Send(s);
}

/*
 * Passive open: listen for a connection on a particular port
 */
void CTcp::tcp_Listen(tcp_Socket *s,word port,procref datahandler,longword timeout)
{
    s->state = tcp_StateLISTEN;
    if ( timeout == 0 ) s->timeout = 0x7ffffff; /* forever... */
    else s->timeout = timeout;
    s->myport = port;
    s->hisport = 0;
    s->seqnum = 0;
    s->dataSize = 0;
    s->flags = 0;
    s->unhappy = 0;
    s->dataHandler = datahandler;
    s->next = tcp_allsocs;
    tcp_allsocs = s;
}

/*
 * Send a FIN on a particular port -- only works if it is open
 */
void CTcp::tcp_Close(tcp_Socket *s)
{
    if ( s->state == tcp_StateESTAB || s->state == tcp_StateSYNREC ) {
        s->flags = tcp_FlagACK | tcp_FlagFIN;
        s->state = tcp_StateFINWT1;
        s->unhappy = true;
    }
}

/*
 * Abort a tcp connection
 */
void CTcp::tcp_Abort(tcp_Socket *s)
{
    if ( s->state != tcp_StateLISTEN && s->state != tcp_StateCLOSED ) {
        s->flags = tcp_FlagRST | tcp_FlagACK;
        tcp_Send(s);
    }
    s->unhappy = 0;
    s->dataSize = 0;
    s->state = tcp_StateCLOSED;
    s->dataHandler(s, 0, -1);
    tcp_Unthread(s);
}

/*
 * Retransmitter - called periodically to perform tcp retransmissions
 */
void CTcp::tcp_Retransmitter()
{
    tcp_Socket *s;
    BOOL x;

    for ( s = tcp_allsocs; s; s = s->next ) {
        x = false;
        if ( s->dataSize > 0 || s->unhappy ) {
            tcp_Send(s);
            x = true;
        }
        if ( x || s->state != tcp_StateESTAB )
            s->timeout -= tcp_RETRANSMITTIME;
        if ( s->timeout <= 0 ) {
            if ( s->state == tcp_StateTIMEWT ) {
                writelog("Closed.");
                s->state = tcp_StateCLOSED;
                s->dataHandler(s, 0, 0);
                tcp_Unthread(s);
            } else {
                writelog("Timeout, aborting");
                tcp_Abort(s);
            }
        }
    }
}

/*
 * Unthread a socket from the socket list, if it's there 
 */
void CTcp::tcp_Unthread(tcp_Socket *ds)
{
    tcp_Socket *s, **sp;

    sp = &tcp_allsocs;
    for (;;) {
        s = *sp;
        if ( s == ds ) {
            *sp = s->next;
            break;
        }
        if ( s == NIL ) break;
        sp = &s->next;
    }
}

/*
 * busy-wait loop for tcp.  Also calls an "application proc"
 */
void CTcp::tcpapp(procref application)
{
    in_Header *ip;
    longword timeout, start;
    int x;

//    sed_Receive(0);

    timeout = 0;
    while ( tcp_allsocs ) {
//        start = clock_ValueRough();
//        ip = sed_IsPacket();//收到包否
        /*If no packet is returned withing 'timeout' milliseconds,
 			 then the routine returns zero.*/
//        if ( ip == NIL ) {//没收到包
//            if ( clock_ValueRough() > timeout ) {
//                tcp_Retransmitter();
//                timeout = clock_ValueRough() + tcp_RETRANSMITTIME;
//            }

            application();

            continue;
//        }

        
//         if ( sed_CheckPacket(ip, 0x800) == 1 ) {//检查是不是IP包
          /* do IP */
			if ( ip->destination == sin_lclINAddr && //检查目标地址是否相符
                 in_GetProtocol(ip) == 6 &&
                 checksum((unsigned short*)ip, in_GetHdrlenBytes(ip)) == 0xFFFF ) {
                tcp_Handler(ip);  //处理收到的IP包
            }
//        }
        /* recycle buffer */
        //sed_Receive(ip);

//        x = clock_ValueRough() - start;
//        timeout -= x;
    }

//    return ( 1 );
}

/*
 * Write data to a connection.
 * Returns number of bytes written, == 0 when connection is not in
 * established state.
 */
int CTcp::tcp_Write(tcp_Socket *s,byte * dp,int len)
{
    int x;

    if ( s->state != tcp_StateESTAB ) len = 0;
    if ( len > (x = tcp_MaxData - s->dataSize) ) len = x;
    if ( len > 0 ) {
        Move(dp, &s->data[s->dataSize], len);
        s->dataSize += len;
        tcp_Flush(s);
    }

    return ( len );
}

/*
 * Send pending data
 */
void CTcp::tcp_Flush(tcp_Socket *s)
{
    if ( s->dataSize > 0 ) {
        s->flags |= tcp_FlagPUSH;
        tcp_Send(s);
    }
}

/*
 * Handler for incoming packets.
 */
void CTcp::tcp_Handler(in_Header *ip)
{
    tcp_Header *tp;
    tcp_PseudoHeader ph;
    int len;
    byte *dp;
    int x, diff;
    tcp_Socket *s;
    word flags;

    len = in_GetHdrlenBytes(ip);
    tp = (tcp_Header *)((byte *)ip + len);//获取IP包中TCP的首部结构
    len = ip->length - len;

    /* demux to active sockets */
    for ( s = tcp_allsocs; s; s = s->next )
        if ( s->hisport != 0 &&
             tp->dstPort == s->myport &&
             tp->srcPort == s->hisport &&
             ip->source == s->hisaddr ) break;
    if ( s == NIL ) {
        /* demux to passive sockets */
        for ( s = tcp_allsocs; s; s = s->next )
            if ( s->hisport == 0 && tp->dstPort == s->myport ) break;
    }
    if ( s == NIL ) {
#ifdef DEBUG
        if ( tcp_logState & tcp_LOGPACKETS ) tcp_DumpHeader(ip, tp, "Discarding");
#endif
        return;
    }

#ifdef DEBUG
    if ( tcp_logState & tcp_LOGPACKETS )
        tcp_DumpHeader(ip, tp, "Received");
#endif

    /* save his ethernet address */
    //MoveW(&((((eth_Header *)ip) - 1)->source[0]), &s->hisethaddr[0], sizeof(eth_HwAddress));

    ph.src = ip->source;
    ph.dst = ip->destination;
    ph.mbz = 0;
    ph.protocol = 6;
    ph.length = len;
    ph.checksum = checksum((word*)tp, len);
    if ( checksum((unsigned short*)&ph, sizeof ph) != 0xffff )
         writelog("bad tcp checksum, received anyway.");

    flags = tp->flags;
    if ( flags & tcp_FlagRST ) {
        writelog("connection reset");
        s->state = tcp_StateCLOSED;
        s->dataHandler(s, 0, -1);
        tcp_Unthread(s);
        return;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -