基于TFTP协议的Eshell源代码

 前几天在看一年前的代码,看到了以前为Windows CE写的内核下载工具-- Eshell.微软也有一个,但当时看了一下TFTP的协议,就自己"造轮子"了,现在把代码贴出来,由于协议描述是件很累人的事情,大家就结合起来看吧.

(协议参考: http://www.longen.org/S-Z/details~z/TFTPProtocol.htm)

调试函数文件:

//------------------------------------------------------------------------------
//
//  File: debug.h
//
//  TFTP source code.
//
//------------------------------------------------------------------------------

#ifndef __DEBUG_H
#define __DEBUG_H

void DEBUGMSG(const char* message,...);

#endif  // DEBUG


//------------------------------------------------------------------------------
//
//  File: debug.c
//
//  TFTP source code.
//
//------------------------------------------------------------------------------
#include <stdarg.h>
#include <stdio.h>
#include "../include/debug.h"
#include <tchar.h>

#ifdef DEBUG

void DEBUGMSG(const char* format, ...)
{
    va_list args;
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
}
#else
void DEBUGMSG(const char* format, ...)
{
    
}

#endif

Packet.h定义了该TFTP协议的数据包格式: RequestPacket, DataPacket, AckPacket, ErrorPacket.根据名字就应该知道是什么意思了吧.
//------------------------------------------------------------------------------
//
//  File: packet.h
//
//  TFTP source code.
//
//------------------------------------------------------------------------------

#ifndef __PACKET_H
#define __PACKET_H

#include <windows.h>

#include <stdio.h>
#define FILE_SIZE 9
#define MODE_SIZE 6
#define DATA_SIZE 512
#define ERR_MSG_SIZE 42
#define DATA_PACKET_SIZE 516
#define TYPE_PACKET_SIZE 9
#define REQ 1 
#define WRQ 2
#define DATA 3
#define ACK 4
#define ERR 5

// Packet Structure Description.

#pragma pack(1)
typedef struct _RequestPacket {
    WORD Opcode;
    TCHAR szFileName[FILE_SIZE];
    TCHAR szMode[MODE_SIZE];
} RequestPacket, *PRequestPacket;

typedef struct _DataPacket {
    WORD Opcode;
    WORD BlockNo;
    TCHAR szData[DATA_SIZE];
} DataPacket, *PDataPacket;

typedef struct __ACKPacket {
    WORD Opcode;
    WORD BlockNo;
} AckPacket, *PACKPacket;

typedef struct _ErrorPacket {
    WORD Opcode;
    WORD ErrorCode;
    TCHAR szErrorMsg[ERR_MSG_SIZE];
} ErrorPacket, *PErrorPacket;
#pragma pack()

typedef enum {READ, WRITE}MODE;

typedef enum {BINARY, ASCII}TYPE;


// Operation Packet.

extern DataPacket MakeDataPacket(const TCHAR* szFileContent,
                                 const int nMsgLength,
                                 const int nBlockNo);

extern AckPacket MakeACKPacket(const int nBlockNo);

extern ErrorPacket MakeErrorPacket(const int nErrorId);

extern RequestPacket MakeRequestPacket(MODE mode,
                                       TYPE type,
                                       const TCHAR* szFileName);
                                      
extern void DisplayErrorMsg(const TCHAR* szMsg);

#endif  // PACKET_H
-------------------------------------------------------------------------------------------------------------------------------------------

packet.cpp是packet.cpp的几个实现,如果现在写的话,肯定会用c++类来封装了,不过如果是应用于纯c环境
的话,可以考虑 用函数指针进行封装.
//------------------------------------------------------------------------------
//
//  File: packet.c
//
//  TFTP source code.
//
//------------------------------------------------------------------------------

#include "../include/packet.h"
#include <winsock2.h>

static TCHAR* szErrMsg[] = {TEXT("Not defined, see error message (if any)."),
                            TEXT("File not found."),
                            TEXT("Access violation."),
                            TEXT("Disk full or allocation exceeded."),
                            TEXT("Illegal TFTP operation."),
                            TEXT("Unknown transfer ID."),
                            TEXT("File already exists."),
                            TEXT("No such user.")};


//------------------------------------------------------------------------------
// Function : MakeDataPacket()
//    Fill file content into data packet.
//
// Input:
//    szMsg [in]: Pointer to a message string.
//   
//    nMsgLength[in]: Message length.
//
//    nBlockNo: Number of  data block.
//
// Output:
//    DataPacket: Prepared data packet to send.
//------------------------------------------------------------------------------
DataPacket MakeDataPacket(const TCHAR* szFileContent,
                          const int nMsgLength,
                          const int nBlockNo)
{
    DataPacket datapack;
    datapack.Opcode = htons(DATA);
    datapack.BlockNo = htons(nBlockNo);
    ZeroMemory(datapack.szData, DATA_SIZE);
    memcpy(datapack.szData, szFileContent, nMsgLength);
    return datapack;                   
}

//------------------------------------------------------------------------------
// Function : MakeACKPacket()
//    Make ACK packet for responding data packet.
//
// Input:
//    nBlockNo [in]: Number of data block.
//
// Output:
//    ACKPacket: Packet to response.
//------------------------------------------------------------------------------
AckPacket MakeACKPacket(const int nBlockNo)
{
    AckPacket ackpack;
    ackpack.Opcode = htons(ACK);
    ackpack.BlockNo = htons(nBlockNo);
    return ackpack;
}

//------------------------------------------------------------------------------
// Function : MakeErrorPacket()
//    Make error packet for dealing with error message.
//
// Input:
//    nErrorId [in]: Error Id to choose error text.
//
// Output:
//    ErrorPacket: Error packet to response.
//------------------------------------------------------------------------------
ErrorPacket MakeErrorPacket(const int nErrorId)
{
    ErrorPacket errpack;
    errpack.Opcode = htons(ERR);
    errpack.ErrorCode = htons(nErrorId);
    ZeroMemory(errpack.szErrorMsg, ERR_MSG_SIZE);
    strcpy(errpack.szErrorMsg, szErrMsg[nErrorId]);
    return errpack;      
}

//------------------------------------------------------------------------------
// Function : MakeRequestPacket()
//    Make request packet for sending or receving message.
//
// Input:
//    mode [in]: Pointer to a message string.
//
//    type [in]: The way to open file.
//
//    szFileName[in]: File name which is filled in request packet.
//
// Output:
//    RequestPacket: packet to request.
//------------------------------------------------------------------------------
RequestPacket MakeRequestPacket(MODE mode, TYPE type, const TCHAR* szFileName)
{
    RequestPacket reqpack;
   
    if (mode == READ)
    {
        reqpack.Opcode = htons(REQ);
    }
    else
    {
        reqpack.Opcode = htons(WRQ);
    }
   
    strcpy(reqpack.szFileName, szFileName);
   
    if (type == BINARY)
    {
        // Binary File.
        strcpy(reqpack.szMode, TEXT("octet/0"));
    }
   
    if (type == ASCII)
    {
        // Text File.
        strcpy(reqpack.szMode, TEXT("netascii"));
    }
   
    return reqpack;
}

//------------------------------------------------------------------------------
// Function : DisplayErrorMsg()
//    Get message string according to error message ID.
//
// Input:
//    szMsg [in]: Message from server.
//
// Output:
//    None.
//------------------------------------------------------------------------------
void DisplayErrorMsg(const TCHAR* szMsg)
{
    DEBUGMSG(szErrMsg[szMsg[3]]);
}
---------------------------------------------------------------------------------------------------------------------------------------------

由于以前项目是个DLL的项目,因此有个dll.h的文件提供接口:

//------------------------------------------------------------------------------
//
//  File: dll.h
//
//  TFTP source code.
//
//------------------------------------------------------------------------------

#ifndef __DLL_H
#define __DLL_H

#include "packet.h"
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else // Not BUILDING_DLL.
# define DLLIMPORT __declspec (dllimport)
#endif // Not BUILDING_DLL.

// Establish connection and initialize socket.
DLLIMPORT DWORD InitalConnection();

// Disconnect and cleanup socket.
DLLIMPORT int CleanupConnection();

// Client sends data packet to server and receives ACK packet from server.
DLLIMPORT int StartClient();

// Send "PUT”request to server and establish communication with server.
DLLIMPORT int HandShake();

// Get the size of file which has been sent to server.
DLLIMPORT int GetSendData();

// Set TFTP parameters: IP address and port.
DLLIMPORT void SetTFTP(const TCHAR* szAddress, const int nPort);

// Set the name of file which is sent to server.
DLLIMPORT void SetFileName(const TCHAR* szFileName);

// Get the size of file which is sent to server.
DLLIMPORT int DoGetFileSize();

#endif //  DLL_H

----------------------------------------------------------------------------------------------------------------------------------------------------
下面就是TFTP.c的描述了,代码比较长,下面两个东西值得注意,DEFAULT_FILENAME是boot.bin完全可以换成
nk.bin (boot.bin是Windows Mobile的bootloader文件, nk.bin是内核文件)
"192.168.100.101"和980分别对应Mobile上面的IP地址和端口号.

///------------------------------------------------------------------------------
//
//  File: Tftp.c
//
//  TFTP source code
//
//------------------------------------------------------------------------------

#define TRANSFER_OVER 0x01
#define ERROR_PACKET 0x02
#define TIME_OUT 0x03
#include "../include/dll.h"    

// Internally used variables.
static SOCKET sock;
static SOCKADDR_IN fromaddr;
static HANDLE g_FileHandle = NULL;
static int HOST_SIZE = 1024;
static TCHAR* DEFAULT_FILENAME = TEXT("boot.bin/0");
static TCHAR g_FileName[128];
static TCHAR g_Address[16] = TEXT("192.168.100.101");
const int g_Port = 980;
static int nMsgLength = 0;
static WORD nBlockNo = 1;
static int g_nSendDataBytes = 0;
TCHAR  pszSendBuffer[DATA_SIZE] = {0};
TCHAR szMsg[DATA_PACKET_SIZE] ={0};

// Internally used functions.
static int SendRequestPacket(const TCHAR* szFileName, TYPE type, MODE mode);
static int SendACKPacket(const int nBlockNo);
static int SendDataPacket(const DataPacket datapacket, const int nDataLength);
static int SendErrorPacket(const int ErrorId);
static int ProcessMsg(const TCHAR* szMsg, const int nMsgLength);
static int GetFile(const TCHAR* szMsg, const int nMsgLength);
static int PutFile(const TCHAR* szMsg, const int nMsgLength);
static int ReceiveMsg(TCHAR* szMsg);
static int PrePareFile(const TCHAR* szFileName, MODE mode);
static WORD GetFileInfo(const TCHAR* szMsg, MODE mode);
static WORD GetBlockNo(TCHAR hightByte, TCHAR lowByte);

//------------------------------------------------------------------------------
// Function : InitalConnection()
//    Establish connection and initalize socket.
//
// Input:
//    None.
//
// Output:
//    0: Initialize connection successfully, otherwise, return GetLastError().
//------------------------------------------------------------------------------
DLLIMPORT DWORD InitalConnection()
{
    WSADATA wsaData;
    WORD wVersionRequested;
    SOCKADDR_IN skaddr;
    int nReturn;
    wVersionRequested = MAKEWORD(2, 2);
    nReturn = WSAStartup(wVersionRequested, &wsaData);
   
    if (nReturn != 0)
    {                                
        return GetLastError();
    }
   
    if (LOBYTE (wsaData.wVersion) != 2 || HIBYTE (wsaData.wVersion) != 2)
    {
         WSACleanup();
         return GetLastError();
    }
   
    // Create socket based on UDP/IP protocol.
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (INVALID_SOCKET == sock)
    {
        return GetLastError();
    }
   
    #ifdef SERVER
    skaddr.sin_family = AF_INET;
    skaddr.sin_port = htons(DEFAULT_PORT);
    skaddr.sin_addr.s_addr = inet_addr(DEFAULT_ADDRESS);
    #else
    skaddr.sin_family = AF_INET;
    skaddr.sin_port = INADDR_ANY;
    skaddr.sin_addr.s_addr = INADDR_ANY;
    #endif
   
    // Bind address to socket.
    nReturn = bind(sock, (struct sockaddr *)&skaddr, sizeof(skaddr)); 
    if(nReturn != 0)
    {
        return GetLastError();
    }
    return 0;
}

//------------------------------------------------------------------------------
// Function : CleanupConnection()
//    Disconnect and cleanup socket.
//
// Input:
//    None.
//
// Output:
//    0.
//------------------------------------------------------------------------------
DLLIMPORT int CleanupConnection()
{
    nBlockNo = 0;
    g_nSendDataBytes = 0;
   
    if (g_FileHandle)
    {
        CloseHandle(g_FileHandle);
    }
   
    WSACleanup();
    closesocket(sock);
    return 0;
}

//------------------------------------------------------------------------------
// Function : SendACKPacket()
//    Send ACK packet to client.
//
// Input:
//    nBlockNo [in]: Number of block.
//
// Output:
//    0: Send ACK packet successfully.
//------------------------------------------------------------------------------
static int SendACKPacket(const int nBlockNo)
{
    AckPacket ackpacket = MakeACKPacket(nBlockNo);
    DEBUGMSG(TEXT("Send Block: %d/n"), nBlockNo);
    int nSendACKBytes = sendto(sock,
                               (const TCHAR*)&ackpacket,
                               sizeof(ackpacket),
                               0,
                               (struct sockaddr*)&fromaddr,
                               sizeof(fromaddr));
                              
    if (SOCKET_ERROR == nSendACKBytes)
    {
        return GetLastError();
    }
   
    return 0;
}

//------------------------------------------------------------------------------
// Function : SendDataPacket()
//    Send data packet to client.
//
// Input:
//    datapacket [in]: Number of block.
//    nDataLength [in]: Length of data.
//
// Output:
//    0: Send data packet successfully.
//------------------------------------------------------------------------------
static int SendDataPacket(const DataPacket datapacket, const int nDataLength)
{
    g_nSendDataBytes += sendto(sock,
                               (const TCHAR*)&datapacket,
                                4 + nDataLength,
                                0,
                                (struct sockaddr*)&fromaddr,
                                sizeof(fromaddr));
                               
    if (SOCKET_ERROR == g_nSendDataBytes)
    {
        return GetLastError();
    }
   
    return 0;
}

//------------------------------------------------------------------------------
// Function : DispatchMsg()
//    This function is used for server side to deal with message.
//    szMsg[1] == REQ: Get read request.
//    szMsg[1] == WRQ: Get write request.
//    szMsg[1] == DATA: Get data packet and send ack packet.
//    szMsg[1] == ACK: Get ack packet and send data packet.
//    szMsg[1] == ERROR: Send error packet.
//
// Input:
//    datapacket [in]: Number of block.
//    nDataLength [in]: Length of data.
//
// Output:
//    0: Send data packet successfully.
//------------------------------------------------------------------------------
static int ProcessMsg(const TCHAR* szMsg, const int nMsgLength)
{
    int nReturn = 0;
   
    switch(szMsg[1])
    {
        case REQ:
             nReturn = GetFileInfo(szMsg, READ);
             nReturn = GetFile(szMsg, nMsgLength);
             break;
            
        case WRQ:
             nReturn = GetFileInfo(szMsg, WRITE);
             nReturn = SendACKPacket(0);
             break;
                 
        case DATA:
             nReturn = PutFile(szMsg, nMsgLength);
             break;
       
        case ACK:
              nReturn = GetFile(szMsg, nMsgLength);
              break;
             
        case ERR:
              nReturn = ERROR_PACKET;
              break;
    }
   
    return nReturn;
}

//------------------------------------------------------------------------------
// Function : GetFile()
//    Get read request from client, read data from file and send data to client.
//
// Input:
//    *fp [in]: Pointer to file.
//
// Output:
//    0: Get File Successfully.
//    TRANSFER_OVER: Read end of file.
//------------------------------------------------------------------------------
static int GetFile(const TCHAR* szMsg, const int nMsgLength)
{
   
    DWORD nBytes;
    int nReturn = 0;
    static BOOL bFirst = TRUE;
    WORD wDummy = GetBlockNo(szMsg[2], szMsg[3]); 
   
    if (!g_FileHandle || !pszSendBuffer)
    {
        return FALSE;
    }
   
    if (wDummy == nBlockNo || bFirst == TRUE)
    {
        // Read File to Buffer.
        if(!ReadFile(g_FileHandle, pszSendBuffer, DATA_SIZE, &nBytes, NULL))
        {
            bFirst = TRUE;
            CloseHandle(g_FileHandle);
            return GetLastError();
        }
       
        if (bFirst == FALSE)
        {
            nBlockNo++;
        }
       
    }  // if (wDummy == nBlockNo || bFirst == TRUE)
   
    DEBUGMSG(TEXT("Receive BlockNo: %d"), wDummy);
    DataPacket datapack = MakeDataPacket(pszSendBuffer, nBytes, nBlockNo);
    DEBUGMSG(TEXT("Send BlockNo: %d/n"), nBlockNo);
   
    // Send Buffer To Client.
    nReturn = SendDataPacket(datapack, nBytes); 
   
    if (nBytes < DATA_SIZE && nReturn == 0)
    {
        nReturn = TRANSFER_OVER;
        bFirst = TRUE;
    } 
   
    bFirst = FALSE;
    return nReturn;
}

//------------------------------------------------------------------------------
// Function : PutFile()
//    Get write request, write data to local server file and send ack packet to
//    client.
//
// Input:
//    *fp [in]: Pointer to file.
//    *szMsg [in]: Pointer to message.
//    nMsgLength [in]: Length of message.
//
// Output:
//    0: Put file successfully.
//    TRANSFER_OVER: Write end of file.
//------------------------------------------------------------------------------
static int PutFile(const TCHAR* szMsg, const int nMsgLength)
{
    DWORD nWriteBytes;
    int nReturn = 0;
    nBlockNo = GetBlockNo(szMsg[2], szMsg[3]);
    DEBUGMSG (TEXT("Receive BlockNo:%d/n"), nBlockNo);
   
    if(!WriteFile(g_FileHandle, szMsg + 4, nMsgLength - 4, &nWriteBytes, NULL))
    {
        DEBUGMSG(TEXT("Write file error/n"));
        CloseHandle(g_FileHandle);
        return GetLastError();
    }
   
    nReturn = SendACKPacket(nBlockNo);
   
    if (nWriteBytes < DATA_SIZE && nReturn == 0)
    {
        nReturn = TRANSFER_OVER;
        CloseHandle(g_FileHandle);
    }
   
    return nReturn;
}



//------------------------------------------------------------------------------
// Function : ReceiveMsg()
//    Receive message from client to fill message buffer.
//
// Input:
//    szMsg [in]: Message buffer.
//
// Output:
//    nMsgLength: Length of filled message.
//------------------------------------------------------------------------------
static int ReceiveMsg(TCHAR* szMsg)
{
    int nLength = sizeof(fromaddr);
    nMsgLength = 0;
    int nTimeout = 1000;
    ZeroMemory(szMsg, DATA_PACKET_SIZE);
    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(int));
    nMsgLength = recvfrom(sock, szMsg, DATA_PACKET_SIZE, 0,
                          (struct sockaddr*)&fromaddr, &nLength); 
    return nMsgLength;
}

//------------------------------------------------------------------------------
// Function : PrePareFile()
//    Client sends request packet to server and establish connection.
//
// Input:
//    szFileName [in]: File name.
//    mode [in]: Read or Write.
//
// Output:
//    0: Prepare file successfully and create a new file handler.
//------------------------------------------------------------------------------
static int PrePareFile(const TCHAR* szFileName, MODE mode)
{
    if (mode == READ)
    {
        g_FileHandle = CreateFile(szFileName,
                                  GENERIC_READ,
                                  0,
                                  NULL,
                                  OPEN_EXISTING,
                                  FILE_ATTRIBUTE_NORMAL,
                                  NULL);
                                  
        DEBUGMSG(TEXT("In read file/n")); 
          
    }
    else if (mode == WRITE)
    {
        g_FileHandle = CreateFile(szFileName,
                                  GENERIC_READ | GENERIC_WRITE,
                                  0,
                                  NULL,
                                  CREATE_ALWAYS,
                                  FILE_ATTRIBUTE_NORMAL,
                                  NULL);
                                    
        DEBUGMSG(TEXT("In write file/n"));
    }
   
    if (g_FileHandle == INVALID_HANDLE_VALUE)
    {
        DEBUGMSG(TEXT("file is invalid/n"));
        return GetLastError();
    }
   
    return 0;
}

//------------------------------------------------------------------------------
// Function : GetFileInfo()
//    Get file name and file type.
//
// Input:
//    szMsg [in]: Pointer to a message string.
//
//    MODE [in]: The way to open file.
//
// Output:
//    0: Get file information successfully.
//------------------------------------------------------------------------------
static WORD GetFileInfo(const TCHAR* szMsg, MODE mode)
{
    TCHAR szFileName[FILE_SIZE];
    int nFilePos = 0;
    int loop = 0;
    int nReturn = 0;
   
    // Get File Name.
    for(loop = 2; loop < DATA_PACKET_SIZE ; loop++)
    {
        szFileName[nFilePos++] = szMsg[loop];
       
        if (szMsg[loop] == 0)
        {
            break;
        }
       
    }  // End of for.
   
    loop++;
    DEBUGMSG(TEXT("File Name is: %s/n"), szFileName);
    nReturn = PrePareFile(szFileName, mode);
    return nReturn;
}

//------------------------------------------------------------------------------
// Function : GetBlockNo()
//    High byte and low byte combine block number.
//
// Input:
//    highByte [in]: Second byte of Message.
//
//    lowByte [in]: Third byte of Message.
//
// Output:
//    wDummy: Block number.
//------------------------------------------------------------------------------
static WORD GetBlockNo(TCHAR hightByte, TCHAR lowByte)
{
    WORD wDummy = 0;
    wDummy = hightByte;
    wDummy <<= 8;
    wDummy |= lowByte & 0x00ff;
    return wDummy;
}

//------------------------------------------------------------------------------
// Function : SendRequestPacket()
//    Client sends request packet to server and establishes connection.
//
// Input:
//    None.
//
// Output:
//    0: Rebind socket successfully.
//------------------------------------------------------------------------------
static int SendRequestPacket(const TCHAR* szFileName, TYPE type, MODE mode)
{
    RequestPacket reqpack = MakeRequestPacket(mode, type, szFileName);
    fromaddr.sin_port = htons(g_Port);
    fromaddr.sin_family = AF_INET;
    fromaddr.sin_addr.s_addr = inet_addr(g_Address);
   
    int nSendReqBytes = sendto(sock,
                               (const TCHAR*)&reqpack,
                               sizeof(reqpack),
                               0,
                               (struct sockaddr*)&fromaddr,
                               sizeof(fromaddr));
                              
    return nSendReqBytes;
}

//------------------------------------------------------------------------------
// Function : SendErrorPacket()
//    Send error packet to server.
//
// Input:
//    None.
//
// Output:
//    0: Send error packet successfully.
//------------------------------------------------------------------------------
static int SendErrorPacket(const int ErrorId)
{
    ErrorPacket errpack = MakeErrorPacket(ErrorId);
   
    int nSendErrBytes = sendto(sock,
                               (const TCHAR*)&errpack,
                               sizeof(errpack),
                               0,
                               (struct sockaddr*)&fromaddr,
                               sizeof(fromaddr));
                              
    DEBUGMSG(TEXT("Error packet size: %d/n"), nSendErrBytes);
    return nSendErrBytes;
}

//------------------------------------------------------------------------------
// Function : SetTFTP()
//    Set TFTP parameters: IP address and port.
//
// Input:
//    szAddress [in]: IP address of target device.
//    nPort [in]: port of target device.
//
// Output:
//    None.
//------------------------------------------------------------------------------
DLLIMPORT void SetTFTP(const TCHAR* szAddress, const int nPort)
{
     strcpy(g_Address, szAddress);
}

//------------------------------------------------------------------------------
// Function : SetFileName()
//    Set the name of file which is sent to server.
//
// Input:
//    None.
//
// Output:
//    None.
//------------------------------------------------------------------------------
DLLIMPORT void SetFileName(const TCHAR* szFileName)
{
    strcpy(g_FileName, szFileName);
}

//------------------------------------------------------------------------------
// Function : HandShake()
//    Sends "PUT" request to server and establish communication with server.
//
// Input:
//    None.
//
// Output:
//    0: Handshake with server successfully, otherwise return GetLastError().
//------------------------------------------------------------------------------
DLLIMPORT int HandShake()
{
    int nRetry = 20;
    int nResult = 0;
    while (1)
    {
        // Send Request Message.
        if (SendRequestPacket(DEFAULT_FILENAME, BINARY, WRITE) == SOCKET_ERROR)
        {
            return GetLastError();
        }
       
        // Get Message.
        nResult = ReceiveMsg(szMsg);
       
        if (nResult < 0)
        {
            if (GetLastError() !=  WSAETIMEDOUT)
            {
                CleanupConnection();
                return GetLastError();
            }
            else
            {
                nRetry--;
                // Time Out.
                if (nRetry == 0)
                {
                    CleanupConnection();
                    return WSAETIMEDOUT;
                }
                Sleep(1000);
            }
        }
        else
        {
            break;
        } // End of if (nResult < 0).
    }
   
    if (PrePareFile(g_FileName, READ) != 0)
    {
        CleanupConnection();
        SendErrorPacket(1);
        return GetLastError();
    }
   
    return 0;
}

//------------------------------------------------------------------------------
// Function : StartClient()
//    Client sends data packet to server and receives ACK packet from server.
//
// Input:
//    None.
//
// Output:
//    0: Client sends server image file successfully.
//------------------------------------------------------------------------------
DLLIMPORT int StartClient()
{
    int nResult = 0;
    int nRetry = 10;
   
    while(1)
    {
        nResult = ProcessMsg(szMsg, nMsgLength);
       
        if (nResult == TRANSFER_OVER)
        {
            DEBUGMSG(TEXT("Transfer over/n"));
            break;
        }
       
        if (nResult != 0)
        {
            DEBUGMSG(TEXT("Error occur, error code = %d/n"), GetLastError());
            break;
        }
       
        nMsgLength = ReceiveMsg(szMsg);
       
        if (nMsgLength < 0)
        {
            if (GetLastError() != WSAETIMEDOUT)
            {
                nResult = GetLastError();
            }
            else
            {
                if (nRetry == 0)
                {
                    nResult = WSAETIMEDOUT;
                    break;
                }
                nRetry--;
                Sleep(1000);
            }
        }
        else
        {
            nRetry = 20;
        } // End of if (nMsgLength < 0).
    } // End while.
    CleanupConnection();
    return nResult;
}

//------------------------------------------------------------------------------
// Function : GetSendData()
//    Get the size of file which has been sent to server.   
//
// Input:
//    None.
//
// Output:
//    int: The size of file which has been sent.
//------------------------------------------------------------------------------
DLLIMPORT int GetSendData()
{
    g_nSendDataBytes -= 4;
    return g_nSendDataBytes;
}

//------------------------------------------------------------------------------
// Function : DoGetFileSize()
//    Get the size of file which is sent to server.
//
// Input:
//    None.
//
// Output:
//    int: The size of file.
//------------------------------------------------------------------------------
DLLIMPORT int DoGetFileSize()
{
    int nFileSize = GetFileSize(g_FileHandle, (LPDWORD) NULL);
    return nFileSize;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值