我需要和一个文件服务器进行通讯,来获取服务器上的某个文件。
接口如下:
一. 报文格式
报文组成为:报文头+报文体。
报文头,共4个字节,用以存放报文体的长度,不包括报文头4个字节。“0100”表示报文体长度为100个字节;
报文体,存放报文具体的内容。
二. 客户端使用接口
int TranFile ( 
char *pszHostName ,  /*主机名称, 在/etc/hosts中定义*/
int   iPortNo ,        /*port number*/
char  *pszCmd,       /*PUT:表示上传文件,GET表示接收文件/
char  *pszFileName    /*文件名称,相对文件路径*/
)三.客户接收文件的处理流程
1.根据主机名称和端口号,和主机建立联机;
2.发送接收文件请求报文,报文格式如下:
报文长度(4)+FILETRANHEADER;
3.接收回应,回应报文格式如下:
报文长度(4)+FILETRANHEADER;
4.根据报文中的处理结果,如果为’0’,表示成功,否则出错;
5.如果成功,接收后续报文。后续报文格式如下:
报文长度(4)+报文序号(8)+结束标志(1)+文件内容
6.接收报文体的回应格式
报文长度(4)+报文序号(8)现在我遇到的问题是在收到第5步后续报文后,无法向服务器发送第6步的回应报文。
程序log如下:
[
发送:00762fil/FILE02200001000039                                                   0 
文件长度为3551
收到:00762fil/FILE02200001000039                                          00003551 0 
收到:0521000000010{
title=内部帐科目分户余额查询                  
trancode=
fld=brc~机构码~0~9~2~NULL
fld=acctno~帐号~0~32~2~NULL
fld=accname~户名~0~70~2~NULL
fld=ccy~币种号~0~3~2~NULL
fld=subctrlcode~科目控制字~0~10~2~NULL
fld=balctrldir~余额方向~0~1~2~<D>借/收 <C>贷/付 <B>双向
fld=lastbal~上日余额~4~18~2~NULL
fld=currbal~当前余额~4~18~2~NULL
fld=seqno~顺序号~1~6~2~NULL
fld=status~帐户状态~0~1~2~<0>正常 <1>销户
fld=lastdate~上一交易日~0~10~2~NULL
fld=termtype~期限类型~0~1~2~<D>天 <M>月 <Y>年
fld=term~期限~1~6~2~NULL
fld=en
]收数据程序如下
Private Sub tcpClient_DataArrival _
 (ByVal bytesTotal As Long)
   Dim strData As String
   Dim filesize As Long   Open "c:\aaa.txt" For Append As #1
   tcpClient.GetData strData
   If Len(strData) = 0 Then
    MsgBox "receve error"
    Exit Sub
   End If
   
   txtOutput.Text = strData
   If Mid(strData, 1, 4) = "0076" Then
    If Mid(strData, 79, 1) = "0" Then
        filesize = Mid(strData, 70, 8)
        Print #1, "文件长度为" & CStr(filesize)
    Else
        MsgBox "请确认文件名是否正确"
    End If
   End If
   If Mid(strData, 1, 4) = "0521" Then
   tcpClient.SendData "0009" & Mid(strData, 5, 8) & Chr(0)
   End If
   Print #1, strData
   Close #1
End Sub程序能够运行到 tcpClient.SendData "0009" & Mid(strData, 5, 8) & Chr(0)
但是运行完就结束了,不会再次进入到tcpClient_DataArrival里面来,请教各位高手这种情况该如何处理。
[email protected]

解决方案 »

  1.   

    首先
    tcpClient.SendData "test"
    判断一下是不是数据的原因
    如果不是数据的原因再检查客户端的发送和服务器端的接收,估计你发送和接收不会错,一般是数据的原因吧
      

  2.   

    你好,谢谢你对这个问题的关注。
    发其它数据我试过,服务器都不回数据,数据错误服务器不会返回数据。而其我无法看到服务器的log,给调试带来了难度。
    现在我又改了一下程序,如下:Private Sub send(sendstr As String)
    MsgBox tcpClient.State
    MsgBox tcpClient.State
    MsgBox tcpClient.State
    DoEvents
    DoEvents
    DoEvents
    DoEvents
    MsgBox tcpClient.State
    MsgBox tcpClient.State
    MsgBox "aaaaaaaaaaaaaaaa" & tcpClient.State
    tcpClient.SendData sendstr
    DoEvents
    MsgBox "send"
    MsgBox tcpClient.State
    End SubPrivate Sub tcpClient_DataArrival(ByVal bytesTotal As Long)
       Dim strData As String
       Dim filesize As Long
        Close #1
       Open "c:\aaa.txt" For Append As #1
       tcpClient.GetData strData
       MsgBox tcpClient.State
       If Len(strData) = 0 Then
        MsgBox "receve error"
        Exit Sub
       End If
       txtOutput.Text = strData
       If Mid(strData, 1, 4) = "0076" Then
        If Mid(strData, 79, 1) = "0" Then
            filesize = Mid(strData, 70, 8)
            Print #1, "文件长度为" & CStr(filesize)
        Else
            MsgBox "请确认文件名是否正确"
        End If
       End If   If Mid(strData, 1, 4) = "0521" Then
            send "0008" & Mid(strData, 5, 8)     
       End If
       
       If Mid(strData, 1, 4) <> "0076" Then
            Open "c:\getfile.txt" For Append As #2
            Print #2, Mid(strData, 14, Len(strData) - 13)
            Close #2
       End If
       Print #1, strData
       
       Close #1
     
    End Sub多调用了一个send函数,在不加那些msgbox和DoEvents时,程序发出后没有错误提示,接收不到返回数据。加了msgbox和DoEvents后,tcpClient.State先打印出7(已连接),经过DoEvents后打印出8(同级人员正在关闭连接).导致发送时报失败。
    我想会不会是不加那些DoEvents,发送时没有报错,但是接收时连接已经变为8(同级人员正在关闭连接)状态.导致接收不到数据。
    还有一点要说明的是服务端肯定没有问题,一直在使用,客户端是c++开发的,没出现过问题。
    附c++代码如下:#include "xlogger.h"
    #include "osgi.h"
    #include "xfile.h"
    #include <fcntl.h>
    #include "rs.h"
    #include "xsocket.h"
    #include "ifiletransfer.h"
    #include "xcommon.h"
    #include <string.h>
    #include <string>#define M_BLKSZ 512struct XTransHd
    {
       char direct_;           /* 1/2:上送/下传*/
       char file_name_[63+1] ; /* 文件名称     */
       char file_size_[8+1] ;  /* 文件长度     */
       char result_[1+1];      /* 处理结果     */
    };
    char _gacIP[M_TCP_LEN_IP+1];
    int  _giPort;/* 由框架赋值的变量 */
    char * _gpcId = NULL;
    IFramework * _gpxFW = NULL;
    /* 提供给框架的事件处理接口 */
    int bhStart(XmlNode *);
    IEventHndlr _gxEH = {bhStart, NULL, initLogger};
    /* 提供给别人的接口 */
    int ftGetFile(char *, char *, char *, char *, char *);
    int ftPutFile(char *, char *, char *, char *, char *);
    IFileTransfer _gxInterface = {ftGetFile, ftPutFile};int bhStart(XmlNode * pxPara)
    {
       M_XRETURN((pxPara == NULL), -1, M_WHERE());
       char * pcIP = XMLGetItemValue(pxPara, "ip", NULL, 0);
       M_XRETURN((pcIP == NULL), -1, M_WHERE());
       strncpy(_gacIP, pcIP, M_TCP_LEN_IP);
       char * pcPort = XMLGetItemValue(pxPara, "port", NULL, 0);
       M_XRETURN((toInt(pcPort, &_giPort) == -1), -1, M_WHERE());
       return 0;
    }int ftGetFile(char * pcID, char * pcLD, char * pcLF, char * pcRD, char * pcRF)
    {
       loginfo("vbs GET--->%s%s-->\n", pcRD, pcRF);
       CRsMngr rs;
       int iSockFD = tcpINETConnect(_gacIP, _giPort);
       M_XRETURN((iSockFD <= 0), -1, M_WHERE());
       rs.rec(iSockFD, freeFD);
       XTransHd xHD;
       memset(&xHD, 0, sizeof(XTransHd));
       xHD.direct_ = '2';
       std::string sR = pcRD;
       sR += pcRF;
       strncpy(xHD.file_name_, sR.c_str(), 63);
       logxbin(LVL_INFO, "first", (char *)&xHD, sizeof(XTransHd));
       int ret = tcpPutData(iSockFD, 0, 4, (char *)&xHD, sizeof(XTransHd));
       M_XRETURN((ret != 0), -1, M_WHERE());
       char * pcData;
       int iDataLen;
       ret = tcpGetData(iSockFD, 0, 4, 15, &pcData, &iDataLen);
       M_XRETURN((ret != 0), -1, M_WHERE());
       memcpy(&xHD, pcData, sizeof(XTransHd));
       free(pcData);
       M_XRETURN((xHD.result_[0] != '0'), -1, M_WHERE());
       logdebug("xHD.result_ = %s\n", xHD.result_);
       int iFileSize;
       M_XRETURN((toInt(xHD.file_size_, &iFileSize) == -1), -1, M_WHERE());
       char * pcFileContent = (char *)calloc(iFileSize+1, sizeof(char));
       rs.rec(pcFileContent, freeHEAP);
       for (int iPos = 0; xHD.result_[0] == '0';)
       {
           int iDataLen;
           ret = tcpGetData(iSockFD, 0, 4, 15L, &pcData, &iDataLen);
           M_XRETURN((ret != 0), -1, M_WHERE());
           xHD.result_[0] = pcData[8];
           memcpy(pcFileContent+iPos, pcData+9, iDataLen-9);
           iPos += (iDataLen-9);
           ret = tcpPutData(iSockFD, 0, 4, pcData, 8);
           free(pcData);
           M_XRETURN((ret != 0), -1, M_WHERE());
       }
       char acPath[M_TCP_LEN_PATH+1];
       memset(acPath, 0, sizeof(acPath));
       std::string sL = pcLD;
       sL += pcLF;
       snprintf(acPath, sizeof(acPath), "%s/%s", getenv("RUNDIR"), sL.c_str());
       ret = putInFile(acPath, "w", pcFileContent, iFileSize);
       M_XRETURN((ret != iFileSize), -1, M_WHERE());
       return 0;
    }int ftPutFile(char * pcID, char * pcLD, char * pcLF, char * pcRD, char * pcRF)
    {
       loginfo("vbs PUT--->%s%s-->\n", pcRD, pcRF);
       CRsMngr rs;
       int iSockFD = tcpINETConnect(_gacIP, _giPort);
       M_XRETURN((iSockFD <= 0), -1, M_WHERE());
       rs.rec(iSockFD, freeFD);
       XTransHd xHD;
       memset(&xHD, 0, sizeof(XTransHd));
       xHD.direct_ = '1';
       std::string sR = pcRD;
       sR += pcLF;
       strncpy(xHD.file_name_, sR.c_str(), 63);
       char acPath[M_TCP_LEN_PATH+1];
       memset(acPath, 0, sizeof(acPath));
       std::string sL = pcLD;
       sL += pcLF;
       snprintf(acPath, sizeof(acPath), "%s/%s", getenv("RUNDIR"), sL.c_str());
       char * pcFileContent;
       int iFileSize = getFileContent(acPath, &pcFileContent);
       M_XRETURN((iFileSize <= 0), -1, M_WHERE());
       rs.rec(pcFileContent, freeHEAP);
       snprintf(xHD.file_size_, sizeof(xHD.file_size_), "%08d", iFileSize);
       int ret = tcpPutData(iSockFD, 0, 4, (char *)&xHD, sizeof(XTransHd));
       M_XRETURN((ret != 0), -1, M_WHERE());
       int iDataLen;
       char * pcData;
       ret = tcpGetData(iSockFD, 0, 4, 15, &pcData, &iDataLen);
       M_XRETURN((ret != 0), -1, M_WHERE());
       memcpy(&xHD, pcData, sizeof(XTransHd));
       free(pcData);
       M_XRETURN((xHD.result_[0] != '0'), -1, M_WHERE());
       int iLeft = iFileSize;
       for (int i = 0, iPos = 0; iLeft > 0; i++)
       {
          char acData[M_BLKSZ+9+1];
          memset(acData, 0, sizeof(acData));
          iDataLen = M_BLKSZ;
          if (iLeft < M_BLKSZ)
             iDataLen = iLeft;
          snprintf(acData, sizeof(acData), "%08d0", i);
          iLeft -= iDataLen;
          if (iLeft <= 0)
             acData[8] = '1';
          memcpy(acData+9, pcFileContent+iPos, iDataLen);
          ret = tcpPutData(iSockFD, 0, 4, acData, iDataLen+9);
          M_XRETURN((ret != 0), -1, M_WHERE());
          iPos += iDataLen;
          ret = tcpGetData(iSockFD, 0, 4, 15, &pcData, &iDataLen);
          M_XRETURN((ret != 0), -1, M_WHERE());
          int iSeqNo = atoi(pcData);
          free(pcData);
          M_XRETURN((i != iSeqNo), -1, M_WHERE());
       }
       return 0;
    }
      

  3.   

    你好,谢谢你对这个问题的关注。
    发其它数据我试过,服务器都不回数据,数据错误服务器不会返回数据。而其我无法看到服务器的log,给调试带来了难度。
    现在我又改了一下程序,如下:Private Sub send(sendstr As String)
    MsgBox tcpClient.State
    MsgBox tcpClient.State
    MsgBox tcpClient.State
    DoEvents
    DoEvents
    DoEvents
    DoEvents
    MsgBox tcpClient.State
    MsgBox tcpClient.State
    MsgBox "aaaaaaaaaaaaaaaa" & tcpClient.State
    tcpClient.SendData sendstr
    DoEvents
    MsgBox "send"
    MsgBox tcpClient.State
    End SubPrivate Sub tcpClient_DataArrival(ByVal bytesTotal As Long)
       Dim strData As String
       Dim filesize As Long
        Close #1
       Open "c:\aaa.txt" For Append As #1
       tcpClient.GetData strData
       MsgBox tcpClient.State
       If Len(strData) = 0 Then
        MsgBox "receve error"
        Exit Sub
       End If
       txtOutput.Text = strData
       If Mid(strData, 1, 4) = "0076" Then
        If Mid(strData, 79, 1) = "0" Then
            filesize = Mid(strData, 70, 8)
            Print #1, "文件长度为" & CStr(filesize)
        Else
            MsgBox "请确认文件名是否正确"
        End If
       End If   If Mid(strData, 1, 4) = "0521" Then
            send "0008" & Mid(strData, 5, 8)     
       End If
       
       If Mid(strData, 1, 4) <> "0076" Then
            Open "c:\getfile.txt" For Append As #2
            Print #2, Mid(strData, 14, Len(strData) - 13)
            Close #2
       End If
       Print #1, strData
       
       Close #1
     
    End Sub多调用了一个send函数,在不加那些msgbox和DoEvents时,程序发出后没有错误提示,接收不到返回数据。加了msgbox和DoEvents后,tcpClient.State先打印出7(已连接),经过DoEvents后打印出8(同级人员正在关闭连接).导致发送时报失败。
    我想会不会是不加那些DoEvents,发送时没有报错,但是接收时连接已经变为8(同级人员正在关闭连接)状态.导致接收不到数据。
    还有一点要说明的是服务端肯定没有问题,一直在使用,客户端是c++开发的,没出现过问题。
    附c++代码如下:#include "xlogger.h"
    #include "osgi.h"
    #include "xfile.h"
    #include <fcntl.h>
    #include "rs.h"
    #include "xsocket.h"
    #include "ifiletransfer.h"
    #include "xcommon.h"
    #include <string.h>
    #include <string>#define M_BLKSZ 512struct XTransHd
    {
       char direct_;           /* 1/2:上送/下传*/
       char file_name_[63+1] ; /* 文件名称     */
       char file_size_[8+1] ;  /* 文件长度     */
       char result_[1+1];      /* 处理结果     */
    };
    char _gacIP[M_TCP_LEN_IP+1];
    int  _giPort;/* 由框架赋值的变量 */
    char * _gpcId = NULL;
    IFramework * _gpxFW = NULL;
    /* 提供给框架的事件处理接口 */
    int bhStart(XmlNode *);
    IEventHndlr _gxEH = {bhStart, NULL, initLogger};
    /* 提供给别人的接口 */
    int ftGetFile(char *, char *, char *, char *, char *);
    int ftPutFile(char *, char *, char *, char *, char *);
    IFileTransfer _gxInterface = {ftGetFile, ftPutFile};int bhStart(XmlNode * pxPara)
    {
       M_XRETURN((pxPara == NULL), -1, M_WHERE());
       char * pcIP = XMLGetItemValue(pxPara, "ip", NULL, 0);
       M_XRETURN((pcIP == NULL), -1, M_WHERE());
       strncpy(_gacIP, pcIP, M_TCP_LEN_IP);
       char * pcPort = XMLGetItemValue(pxPara, "port", NULL, 0);
       M_XRETURN((toInt(pcPort, &_giPort) == -1), -1, M_WHERE());
       return 0;
    }int ftGetFile(char * pcID, char * pcLD, char * pcLF, char * pcRD, char * pcRF)
    {
       loginfo("vbs GET--->%s%s-->\n", pcRD, pcRF);
       CRsMngr rs;
       int iSockFD = tcpINETConnect(_gacIP, _giPort);
       M_XRETURN((iSockFD <= 0), -1, M_WHERE());
       rs.rec(iSockFD, freeFD);
       XTransHd xHD;
       memset(&xHD, 0, sizeof(XTransHd));
       xHD.direct_ = '2';
       std::string sR = pcRD;
       sR += pcRF;
       strncpy(xHD.file_name_, sR.c_str(), 63);
       logxbin(LVL_INFO, "first", (char *)&xHD, sizeof(XTransHd));
       int ret = tcpPutData(iSockFD, 0, 4, (char *)&xHD, sizeof(XTransHd));
       M_XRETURN((ret != 0), -1, M_WHERE());
       char * pcData;
       int iDataLen;
       ret = tcpGetData(iSockFD, 0, 4, 15, &pcData, &iDataLen);
       M_XRETURN((ret != 0), -1, M_WHERE());
       memcpy(&xHD, pcData, sizeof(XTransHd));
       free(pcData);
       M_XRETURN((xHD.result_[0] != '0'), -1, M_WHERE());
       logdebug("xHD.result_ = %s\n", xHD.result_);
       int iFileSize;
       M_XRETURN((toInt(xHD.file_size_, &iFileSize) == -1), -1, M_WHERE());
       char * pcFileContent = (char *)calloc(iFileSize+1, sizeof(char));
       rs.rec(pcFileContent, freeHEAP);
       for (int iPos = 0; xHD.result_[0] == '0';)
       {
           int iDataLen;
           ret = tcpGetData(iSockFD, 0, 4, 15L, &pcData, &iDataLen);
           M_XRETURN((ret != 0), -1, M_WHERE());
           xHD.result_[0] = pcData[8];
           memcpy(pcFileContent+iPos, pcData+9, iDataLen-9);
           iPos += (iDataLen-9);
           ret = tcpPutData(iSockFD, 0, 4, pcData, 8);
           free(pcData);
           M_XRETURN((ret != 0), -1, M_WHERE());
       }
       char acPath[M_TCP_LEN_PATH+1];
       memset(acPath, 0, sizeof(acPath));
       std::string sL = pcLD;
       sL += pcLF;
       snprintf(acPath, sizeof(acPath), "%s/%s", getenv("RUNDIR"), sL.c_str());
       ret = putInFile(acPath, "w", pcFileContent, iFileSize);
       M_XRETURN((ret != iFileSize), -1, M_WHERE());
       return 0;
    }int ftPutFile(char * pcID, char * pcLD, char * pcLF, char * pcRD, char * pcRF)
    {
       loginfo("vbs PUT--->%s%s-->\n", pcRD, pcRF);
       CRsMngr rs;
       int iSockFD = tcpINETConnect(_gacIP, _giPort);
       M_XRETURN((iSockFD <= 0), -1, M_WHERE());
       rs.rec(iSockFD, freeFD);
       XTransHd xHD;
       memset(&xHD, 0, sizeof(XTransHd));
       xHD.direct_ = '1';
       std::string sR = pcRD;
       sR += pcLF;
       strncpy(xHD.file_name_, sR.c_str(), 63);
       char acPath[M_TCP_LEN_PATH+1];
       memset(acPath, 0, sizeof(acPath));
       std::string sL = pcLD;
       sL += pcLF;
       snprintf(acPath, sizeof(acPath), "%s/%s", getenv("RUNDIR"), sL.c_str());
       char * pcFileContent;
       int iFileSize = getFileContent(acPath, &pcFileContent);
       M_XRETURN((iFileSize <= 0), -1, M_WHERE());
       rs.rec(pcFileContent, freeHEAP);
       snprintf(xHD.file_size_, sizeof(xHD.file_size_), "%08d", iFileSize);
       int ret = tcpPutData(iSockFD, 0, 4, (char *)&xHD, sizeof(XTransHd));
       M_XRETURN((ret != 0), -1, M_WHERE());
       int iDataLen;
       char * pcData;
       ret = tcpGetData(iSockFD, 0, 4, 15, &pcData, &iDataLen);
       M_XRETURN((ret != 0), -1, M_WHERE());
       memcpy(&xHD, pcData, sizeof(XTransHd));
       free(pcData);
       M_XRETURN((xHD.result_[0] != '0'), -1, M_WHERE());
       int iLeft = iFileSize;
       for (int i = 0, iPos = 0; iLeft > 0; i++)
       {
          char acData[M_BLKSZ+9+1];
          memset(acData, 0, sizeof(acData));
          iDataLen = M_BLKSZ;
          if (iLeft < M_BLKSZ)
             iDataLen = iLeft;
          snprintf(acData, sizeof(acData), "%08d0", i);
          iLeft -= iDataLen;
          if (iLeft <= 0)
             acData[8] = '1';
          memcpy(acData+9, pcFileContent+iPos, iDataLen);
          ret = tcpPutData(iSockFD, 0, 4, acData, iDataLen+9);
          M_XRETURN((ret != 0), -1, M_WHERE());
          iPos += iDataLen;
          ret = tcpGetData(iSockFD, 0, 4, 15, &pcData, &iDataLen);
          M_XRETURN((ret != 0), -1, M_WHERE());
          int iSeqNo = atoi(pcData);
          free(pcData);
          M_XRETURN((i != iSeqNo), -1, M_WHERE());
       }
       return 0;
    }
      

  4.   

    你是不是想把C++的客户端改成VB的?服务器端是用什么开发的?
      

  5.   

    是啊,改为vb的,服务器端在aix平台,应该是c++做的