非阻塞方式传文件﹐继续提问

storm999 2005-11-02 03:56:23
问题还是没有解决﹐继续提问

netsys2(来电!) 说
你是死循环调用的方式,不好!
Socket->ReceiveBuf(buf, nLen) 时返回值总是-1,
->. ReceiveBuf returns the number of bytes actually read. If no bytes are read, ReceiveBuf returns -1.
就是说对方还没有来得及发数据,你就拼命读。
另外,阻塞和非阻塞读的方式不一致,阻塞时是要读到数据才返回(或者错误),而非阻塞是有数据才通知你,然后你再读,不是傻傻的一直读。
可是我有判断啊﹐如果返回值是-1就退出啊

你能不能帖出一段代码让我看看﹐多谢了
...全文
590 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
jsfserver 2005-11-29
  • 打赏
  • 举报
回复
case FD_READ: //当套接字收到数据时通知,
自定义接受函数,接受套接字上收到的数据
上面写错了,是自己调用接受函数recv()接受数据
jsfserver 2005-11-29
  • 打赏
  • 举报
回复
我最近也在研究这个,不过我研究的是最底层的实现,也就是在C++Builder中用调用API实现的,
用的是异步数据传输机制,为非阻塞模式,调用WSAAsyncSelect()来响应Socket上的各类消息
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT: //当套接字收到外来连接时通知.
调用accept().建立新连接
case FD_READ: //当套接字收到数据时通知,
自定义接受函数,接受套接字上收到的数据
.........
}
我现在只做到指定数据发送过来能收到,而且很顺利,但是问题是传过来的数据包并不完整时如何判断处理,这是我下个星期研究的问题,光上面的API实现就快花了我一个星期,不过很开心,不用MFC和VCL,自己实现了非阻塞模式的数据准确接受,不过还有很多问题要解决!
zyyoung 2005-11-21
  • 打赏
  • 举报
回复
up
「已注销」 2005-11-21
  • 打赏
  • 举报
回复
学习
L·D·N 2005-11-14
  • 打赏
  • 举报
回复
领教了~确实复杂呀~!
wizardqi 2005-11-05
  • 打赏
  • 举报
回复
//测试程序头文件
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdTCPServer.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
#include "TransUnit.cpp"

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TIdTCPServer *IdTCPServer1;
TButton *SendMsgBtn;
TMemo *Memo1;
TButton *SendFileBtn;
void __fastcall IdTCPServer1Execute(TIdPeerThread *AThread);
void __fastcall IdTCPServer1Connect(TIdPeerThread *AThread);
void __fastcall IdTCPServer1Disconnect(TIdPeerThread *AThread);
void __fastcall FormCreate(TObject *Sender);
void __fastcall SendMsgBtnClick(TObject *Sender);
void __fastcall SendFileBtnClick(TObject *Sender);
private: // User declarations
TTransClientThread *Client1,*Client2;
public: // User declarations
void __fastcall ClientOnReadFile(TIdTCPClient* IdTCPClient,AnsiString FromID,AnsiString FileName,int FileSize);
void __fastcall ClientOnReadMsg(TIdTCPClient* IdTCPClient,AnsiString FromID,AnsiString Msg);
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

//---------------------------------------------------------------------------
//测试程序源文件
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
struct TClientInfo:TObject{
AnsiString ClientID;
TIdPeerThread * Thread;
};
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ClientOnReadFile(TIdTCPClient* IdTCPClient,AnsiString FromID,AnsiString FileName,int FileSize)
{
TFileStream *FS=new TFileStream("d:\\"+FileName,fmCreate | fmShareDenyNone);
try{
IdTCPClient->ReadStream(FS,FileSize);
Memo1->Lines->Add(FromID+" send file:"+FileName+" and save to d:\\");
}
catch(...)
{
}
delete FS;
}
void __fastcall TForm1::ClientOnReadMsg(TIdTCPClient* IdTCPClient,AnsiString FromID,AnsiString Msg)
{
Memo1->Lines->Add(FromID+" said that:"+Msg);
}


void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
AnsiString ClientID;
TList * ThreadList;
char *PBuffer=NULL;
int ReadSize;
ClientID=AThread->Connection->ReadLn();
ReadSize=AThread->Connection->ReadInteger();
PBuffer= new char[ReadSize];
AThread->Connection->ReadBuffer(PBuffer,ReadSize);
ThreadList=IdTCPServer1->Threads->LockList();
//----------------------------------------------------------------------------
int Index=0;
while((Index<ThreadList->Count) && (ClientID!=((TClientInfo *)((TIdPeerThread *)ThreadList->Items[Index])->Data)->ClientID))Index++;
if(Index<ThreadList->Count)
try{
((TIdPeerThread *)ThreadList->Items[Index])->Connection->WriteLn(((TClientInfo *)AThread->Data)->ClientID);
((TIdPeerThread *)ThreadList->Items[Index])->Connection->WriteBuffer(PBuffer,ReadSize,True);
}
catch(...)
{
((TIdPeerThread *)ThreadList->Items[Index])->Stop();
}
IdTCPServer1->Threads->UnlockList();
if(PBuffer!=NULL)delete PBuffer;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::IdTCPServer1Connect(TIdPeerThread *AThread)
{
TClientInfo *pCI=new TClientInfo();
pCI->ClientID=AThread->Connection->ReadLn();
pCI->Thread=AThread;
AThread->Data=pCI;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdTCPServer1Disconnect(TIdPeerThread *AThread)
{
AThread->Data->Free();
AThread->Data=NULL;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Client1=new TTransClientThread();
Client1->Host="127.0.0.1";
Client1->Port=1981;
Client1->RegName="Client one";
Client1->OnReadMsg=ClientOnReadMsg;
Client1->OnReadFile=ClientOnReadFile;
Client1->Start();
Client2=new TTransClientThread();
Client2->Host="127.0.0.1";
Client2->Port=1981;
Client2->RegName="Client two";
Client2->OnReadMsg=ClientOnReadMsg;
Client2->OnReadFile=ClientOnReadFile;
Client2->Start();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SendMsgBtnClick(TObject *Sender)
{
Client1->SendMsg("Client two","quanqi");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SendFileBtnClick(TObject *Sender)
{
Client2->SendFile("Client one","c:\\haohao.jpg");
}
//---------------------------------------------------------------------------
wizardqi 2005-11-05
  • 打赏
  • 举报
回复
/*
我想问题的关键就在于你使用了非阻塞方式中的“消息模式”,也就是说。。。。
楼主同样的问题在Delphi中也问过,现将我的BCB版本也贴出来供楼主研究.
*/
/*
TransUnit.cpp:
实现中转功能
*/
#include <classes.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdTCPServer.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
const
CMD_MSG=1000,
CMD_FILE=1001;
typedef void __fastcall (__closure * TTransClientReadMsgEvent)(TIdTCPClient* IdTCPClient,AnsiString FromID,AnsiString Msg);
typedef void __fastcall (__closure * TTransClientReadFileEvent)(TIdTCPClient* IdTCPClient,AnsiString FromID,AnsiString FileName,int FileSize);

struct TFileInfo{
char FileName[125];
int FileSize;
};

class TTransClientThread:public TThread{
private:
TIdTCPClient* FIdTCPClient;
AnsiString FHost;
int FPort;
AnsiString FRegName;
TTransClientReadMsgEvent FOnReadMsg;
TTransClientReadFileEvent FOnReadFile;
void __fastcall DoOnReadMsg(AnsiString ClientID);
void __fastcall DoOnReadFile(AnsiString ClientID);
public:
__fastcall TTransClientThread();
__fastcall ~TTransClientThread();
void __fastcall Start();
void __fastcall SendFile(AnsiString ClientID,AnsiString FileName);
void __fastcall SendMsg(AnsiString ClientID,AnsiString Msg);
virtual void __fastcall Execute(void);
__property TIdTCPClient* IdTCPClient ={read=FIdTCPClient};
__property AnsiString Host ={read=FHost,write=FHost};
__property int Port ={read=FPort,write=FPort};
__property AnsiString RegName ={read=FRegName,write=FRegName};
__property TTransClientReadMsgEvent OnReadMsg ={read=FOnReadMsg,write=FOnReadMsg};
__property TTransClientReadFileEvent OnReadFile ={read=FOnReadFile,write=FOnReadFile};
};

__fastcall TTransClientThread::TTransClientThread():TThread(true)
{
FreeOnTerminate=true;
FIdTCPClient=new TIdTCPClient(NULL);
}

__fastcall TTransClientThread::~TTransClientThread()
{
delete FIdTCPClient;
}

void __fastcall TTransClientThread::Start()
{
FIdTCPClient->Host=FHost;
FIdTCPClient->Port=FPort;
Resume();
}

void __fastcall TTransClientThread::SendFile(AnsiString ClientID,AnsiString FileName)
{
TFileStream *FS=new TFileStream(FileName,fmOpenRead | fmShareDenyNone);
try{
int DataLen,CMDID=CMD_FILE;
TFileInfo FI;
strcpy(FI.FileName,ExtractFileName(FileName).c_str());
FI.FileSize=FS->Size;
if(FIdTCPClient->Connected())
{
FIdTCPClient->WriteLn(ClientID);
DataLen=sizeof(CMDID)+sizeof(FI)+FI.FileSize;
FIdTCPClient->WriteInteger(DataLen);
FIdTCPClient->OpenWriteBuffer();
FIdTCPClient->WriteBuffer(&CMDID,sizeof(CMDID));
FIdTCPClient->WriteBuffer(&FI,sizeof(FI));
FIdTCPClient->WriteStream(FS);
FIdTCPClient->CloseWriteBuffer();
}
}
catch(...)
{
}
delete FS;
}

void __fastcall TTransClientThread::SendMsg(AnsiString ClientID,AnsiString Msg)
{
int MsgLen,DataLen,CMDID=CMD_MSG;
if(FIdTCPClient->Connected())
{
FIdTCPClient->WriteLn(ClientID);
MsgLen=Msg.Length();
DataLen=sizeof(CMDID)+sizeof(MsgLen)+MsgLen;
FIdTCPClient->WriteInteger(DataLen);
FIdTCPClient->OpenWriteBuffer();
FIdTCPClient->WriteBuffer(&CMDID,sizeof(CMDID));
FIdTCPClient->WriteBuffer(&MsgLen,sizeof(MsgLen));
FIdTCPClient->WriteBuffer(Msg.c_str(),MsgLen);
FIdTCPClient->CloseWriteBuffer();
}
}


void __fastcall TTransClientThread::Execute(void)
{
int CMDID;
AnsiString ClientID;
FIdTCPClient->Connect();
if(FIdTCPClient->Connected())FIdTCPClient->WriteLn(RegName);
while(!Terminated && FIdTCPClient->Connected()){
ClientID=FIdTCPClient->ReadLn();
FIdTCPClient->ReadBuffer(&CMDID,sizeof(CMDID));
switch(CMDID){
case CMD_MSG:
DoOnReadMsg(ClientID);
break;
case CMD_FILE:
DoOnReadFile(ClientID);
break;
}
}
}

void __fastcall TTransClientThread::DoOnReadMsg(AnsiString ClientID)
{
int ReadLen;
AnsiString Msg;
FIdTCPClient->ReadBuffer(&ReadLen,sizeof(ReadLen));
Msg.SetLength(ReadLen);
FIdTCPClient->ReadBuffer(Msg.c_str(),ReadLen);
if(FOnReadMsg!=NULL)FOnReadMsg(FIdTCPClient,ClientID,Msg);
}
void __fastcall TTransClientThread::DoOnReadFile(AnsiString ClientID)
{
TFileInfo FI;
FIdTCPClient->ReadBuffer(&FI,sizeof(FI));
if(FOnReadFile!=NULL)FOnReadFile(FIdTCPClient,ClientID,FI.FileName,FI.FileSize);
}
shadowstar 2005-11-03
  • 打赏
  • 举报
回复
---》WINDOWS程序的栈内存大小是有限制的,CB中在LINKER页设置,如果你的程序包括较深的调用,
如递归等,常常发生栈溢出错误!

这种情况很少,的确有这种情况的时候再考虑。

netsys2 2005-11-03
  • 打赏
  • 举报
回复
OnRead中,你无法预估有多大的数据过来

-->在非阻塞模式中可以通过Socket->ReceiveLength来判定目前有多少数据,然后把他们一次性全读出来!

netsys2 2005-11-03
  • 打赏
  • 举报
回复
这个我也有不同意见。

“说是 char buf[4096]; 会把系统搞死,没有那么严重。”

---》WINDOWS程序的栈内存大小是有限制的,CB中在LINKER页设置,如果你的程序包括较深的调用,
如递归等,常常发生栈溢出错误!

因此对于大内存使用,比较规范的做法是用堆申请的模式(为了避免碎片,可以采用自定义内存池)。

kinglh 2005-11-03
  • 打赏
  • 举报
回复
收藏先
jishiping 2005-11-03
  • 打赏
  • 举报
回复
netsys2 的部分意见不敢认同。说是 char buf[4096]; 会把系统搞死,没有那么严重。

2)一端用循环拼命收,遇到-1就认为结束,实际上是暂时没有数据
-------------------------------------------------------------
你一句,应该是netsys2没有看清楚代码。在一个OnRead中,你无法预估有多大的数据过来,所以用循环多次读取。当读不到数据时(-1),退出本次的OnRead事件的读取。实际上客户端并没有结束文件的读取。代码中已经用Size来表示文件长度了,只有当Size<=0时,才结束文件的读取。

楼主一直没有说 _toUserInfor.count(Socket) 以及 _actFileInfo.count(Socket) 是怎么回事。
楼主在另一个帖子中说的“后面的包也触发了服务器的ClientRead事件﹐只是在调用Socket->ReceiveBuf(buf, nLen) 时返回值总是-1”,我认为是不可能的。只要触发了OnRead事件,不可能读不到数据。你说的联网测试,是Internet还是局域网?
storm999 2005-11-03
  • 打赏
  • 举报
回复
楼主一直没有说 _toUserInfor.count(Socket) 以及 _actFileInfo.count(Socket) 是怎么回事。
----------------------------------------------------------------------------------
_toUserInfor和_actFileInfo是一个map,我用当前Socket作为关键词﹐__toUserInfor中和Socket对应的值是结构SocketFile。保存的信息产要是当前SOCKET正在传送文件的总长度﹐和已读长度等﹐_actFileInfo和_toUserInfor同样﹐也是接收到的文件的一些信息
_toUserInfor.count(Socket)是判断SocketFile中间服务器是不是第一次发文件﹐如果是﹐就创建一个SocketFile﹐并把当前Socket和这个SocketFile加到_toUserInfor中﹐并且﹐读出文件总大小等信息(在发送文件的第一个包里)。以后每当从这个Socket得到据﹐就在文件总长度中减去读到的数据长度﹐如果文件总长度为0﹐则表示文件已接收完。

楼主在另一个帖子中说的“后面的包也触发了服务器的ClientRead事件﹐只是在调用Socket->ReceiveBuf(buf, nLen) 时返回值总是-1”,我认为是不可能的。只要触发了OnRead事件,不可能读不到数据。你说的联网测试,是Internet还是局域网?
-------------------------------------------------------------------------
真的是这样﹐我也搞不懂﹐在测试的时候﹐如果我客户端一次一次的调用SendBuf(buf, nlen),服务器端在调试的状况下我看到﹐前面几次还行﹐后面很多次虽然触发了ClientRead事件﹐可ReceiveLength()得到的结果也是-1,ReceiveBuf(buf, nLen)返回的也是-1,这种状况﹐甚至在服务器﹐和客户端在同一台机子上就会出现。后来我把数据先放到一个TMemoryStream中﹐用SendStream一次发出﹐好像服务器端是能收完整数据了﹐但服务器端用同样的方法﹐接收方的客户端却还是收不完数据﹐奇怪的是﹐服务器如果和接收方在同一台机子上﹐接收方就能接受完整的数据﹐如果是两台机子﹐就收不完整。我用来测试的文件只有10几M而已。所以﹐我认为﹐其中一定还有什么东西我没有注意到。
storm999 2005-11-02
  • 打赏
  • 举报
回复
正确的发送流程是:

1)SERVER和CLIENT握手,SERVER发送文件名称、大小等信息给CLIENT

2)CLIENT响应,准备接收

3)SERVER先发送一包数据(由于TCP自己有算法控制,大了也没用,一次8K足够),带上这包的序列号

4)CLIENT成功接受这包,然后通知SERVER发下一包。
----------------------------------------------------------------------
受教了﹐這樣好像比較復雜﹐我是第一次作Socket程序﹐老大能不能提供一些參考的代碼啊﹗如果分數不行﹐我們可以使用現金﹐因為我現在是非常著急﹐答應朋友的東西﹐一直沒有完成﹗
我的信箱是999zhaorui@163.com
MSN是storm_zr@hotmail.com,公司里上不了﹐如果有興趣﹐晚上10點鐘後可以聯系我
netsys2 2005-11-02
  • 打赏
  • 举报
回复
char buf[4096];

这句毛病大了!

你会把系统搞死的,

记住,凡是超过200BYTE的,最好用new来申请!
netsys2 2005-11-02
  • 打赏
  • 举报
回复
可是我有判断啊﹐如果返回值是-1就退出啊

----->对方还没有发完,你就退出了!

数据从来不是连续不断来的,它总是一个包一个包来,然后TCP组装后给你,

一个稳定可靠的系统应该这样:

正确的发送流程是:

1)SERVER和CLIENT握手,SERVER发送文件名称、大小等信息给CLIENT

2)CLIENT响应,准备接收

3)SERVER先发送一包数据(由于TCP自己有算法控制,大了也没用,一次8K足够),带上这包的序列号

4)CLIENT成功接受这包,然后通知SERVER发下一包。

重复3,4直到完成。


你以前的方法错误有3:

1)一端用循环拼命发,也不管发送成功没有(去查询TCP的窗口概念),结果很多数据实际没有发出

2)一端用循环拼命收,遇到-1就认为结束,实际上是暂时没有数据

3)系统可靠性太差,传输一个大文件,万一中间网络断了或者写盘失败,双方都不知道!



因此:

你必须重新设计你的代码,把以前写的垃圾扔了,看看我以前的帖子来设计传输协议,然后
编程吧!
shadowstar 2005-11-02
  • 打赏
  • 举报
回复
这套组件是写的不够理想,所以Borland已经放弃了,但也肯定不会有问题,毕竟那么多人用了那么多年了。

代码有点长,不好意思,没时间仔细阅读,如果只是转发文件的话应该不需要这么多代码量。
storm999 2005-11-02
  • 打赏
  • 举报
回复
如果接受方客戶端和服務器在同一台機子上﹐文件就能傳送完﹐可如果接受方客戶端和服務器不在同一台機上﹐就經常收不到後面的包﹐所以我懷疑和組件自身的性能有關
以下是程序代碼

客戶端發文件
void TSockClient::sendFile(char* filename, int fid)
{
int hFile;
byte buf[4096];
int nLen;
int cmd = IDE_SENDFILE;
if (!FClient->Active)
FClient->Active = true;
TMemoryStream *mStream = new TMemoryStream();
hFile = FileOpen(AnsiString(filename), fmOpenRead);
int nSize = GetFileSize((HANDLE)hFile, NULL);
mStream->Write(&fid, 4);
mStream->Write(&cmd, 4);
mStream->Write(&nSize, 4);
int i = 0;
for(; nSize>0; nSize -= nLen) {
nLen = std::min((int)sizeof(buf), nSize);
nLen = FileRead(hFile, buf, nLen);
if (nLen<=0) break;
mStream->Write(buf, nLen);
i += nLen;
}
int j = 0;
mStream->Seek(0, soFromBeginning);
FClient->Socket->SendStream(mStream);
FileClose(hFile);
}

服務端收并轉發文件
void __fastcall TCSService::FSocketClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
int fid;
int cmd;
int nSize;
int nLen;
char buf[4096];

SocketFile *sf;
TCustomWinSocket *rSocket;

if (_toUserInfor.count(Socket)==0)
{
nLen = Socket->ReceiveBuf(&fid, 4);
if (nLen < 0)
return;
Socket->ReceiveBuf(&cmd, 4);
if (cmd == IDE_RECEIVEFILE)
{
_rcvScks[fid] = Socket;
return;
}
else if(cmd == IDE_SENDFILE){
Socket->ReceiveBuf(&nSize, 4);
sf = new struct SocketFile();
sf->nSize = nSize;
sf->fid = fid;
_toUserInfor[Socket] = sf;
rSocket = _rcvScks[fid];
sf->mStream = new TMemoryStream();
sf->mStream->WriteBuffer(&fid, 4);
sf->mStream->WriteBuffer(&nSize, 4);
}
}
else{
sf = _toUserInfor[Socket];
rSocket = _rcvScks[sf->fid];
}
while (sf->nSize > 0){
nLen = std::min(sf->nSize, sizeof(buf));
nLen = Socket->ReceiveBuf(buf, nLen);
if (nLen <= 0)
break;
sf->mStream->WriteBuffer(buf, nLen);
sf->nSize -= nLen;
}
if (sf->nSize <= 0)
{
sf->mStream->Seek(0, soFromBeginning);
rSocket->SendStream(sf->mStream);
if (_toUserInfor.count(Socket)){
sf = _toUserInfor[Socket];
_toUserInfor.erase(Socket);
delete sf;
}
}
}

客戶端收文件
void __fastcall TSockClient::FClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
int nLen;
int nSize;
int fid;
char buf[4096];

nLen = Socket->ReceiveLength();
if (nLen <= 0) {
return;
}
SocketFile *sf;
if (_actFileInfo.count(Socket)==0)
{
nLen = Socket->ReceiveBuf(&fid, 4);
if (nLen < 0)
return;
Socket->ReceiveBuf(&nSize, 4);
sf = new struct SocketFile();
sf->nSize = nSize;
sf->fid = fid;
//
if (_actFiles.count(fid))
{
AnsiString fname = ExtractFileName(_actFiles[fid]);
fname = "C:\\" + fname;
if (FileExists(fname)){
DeleteFile(fname);
}
sf->fStream = new TFileStream(fname, fmCreate);
}
_actFileInfo[Socket] = sf;
//
}
else{
sf = _actFileInfo[Socket];
}
while (sf->nSize > 0){
nLen = std::min(sf->nSize, sizeof(buf));
nLen = Socket->ReceiveBuf(buf, nLen);
if (nLen <= 0)
break;
sf->fStream->WriteBuffer(buf, nLen);
sf->nSize -= nLen;
}
if (sf->nSize <= 0)
{
if (_actFileInfo.count(Socket)){
sf = _actFileInfo[Socket];
_actFileInfo.erase(Socket);
delete sf->fStream;
delete sf;
}
}
}
shadowstar 2005-11-02
  • 打赏
  • 举报
回复
可以写成这样:

int len = Socket->ReceiveLength();
char* buf = new char[len];

try {
Socket->ReceiveBuf(buf, len);
}
__finally {
delete buf;
}
shadowstar 2005-11-02
  • 打赏
  • 举报
回复
Note:
While the ReceiveLength method can return an estimate of the size of buffer required to retrieve information from the socket, the number of bytes it returns is not necessarily accurate.

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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