vb用winsock通讯问题

blire 2008-10-20 04:28:59
我需要和一个文件服务器进行通讯,来获取服务器上的某个文件。
接口如下:
一. 报文格式
报文组成为:报文头+报文体。
报文头,共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里面来,请教各位高手这种情况该如何处理。
blire@sina.com
...全文
104 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
blire 2008-10-21
  • 打赏
  • 举报
回复
是啊,改为vb的,服务器端在aix平台,应该是c++做的
tongnaifu 2008-10-21
  • 打赏
  • 举报
回复
你是不是想把C++的客户端改成VB的?服务器端是用什么开发的?
blire 2008-10-21
  • 打赏
  • 举报
回复
你好,谢谢你对这个问题的关注。
发其它数据我试过,服务器都不回数据,数据错误服务器不会返回数据。而其我无法看到服务器的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 Sub

Private 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 512

struct 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;
}

blire 2008-10-21
  • 打赏
  • 举报
回复
你好,谢谢你对这个问题的关注。
发其它数据我试过,服务器都不回数据,数据错误服务器不会返回数据。而其我无法看到服务器的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 Sub

Private 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 512

struct 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;
}

tongnaifu 2008-10-21
  • 打赏
  • 举报
回复
首先
tcpClient.SendData "test"
判断一下是不是数据的原因
如果不是数据的原因再检查客户端的发送和服务器端的接收,估计你发送和接收不会错,一般是数据的原因吧
tongnaifu 2008-10-21
  • 打赏
  • 举报
回复
不同语言之间的通讯就不知道了,帮顶

1,502

社区成员

发帖
与我相关
我的任务
社区描述
VB 网络编程
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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