关于 TClientSocket1和TClientSocket1 有 Socket->SendStream() 为什么没有Socket->ReceiveStream(),在线等待50分

iec 2002-06-25 09:38:20
如果客户端用 Socket->SendStream()
那么服务器端应该怎么接收数据
好象没有 Socket->ReceiveStream()这个函数
...全文
127 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
sncel 2002-06-25
  • 打赏
  • 举报
回复
SeneStream发送就用ReceiveBuf接收。
Server:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include "Jpeg.hpp"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMemoryStream *tmpStream=new TMemoryStream;
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------


void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
String RevText;
RevText=Socket->ReceiveText();
if (RevText=="GetImage")
{
TCanvas * tDesktop=new TCanvas;
Graphics::TBitmap *tbitmap = new Graphics::TBitmap;
TJPEGImage * tjpeg=new TJPEGImage;
tDesktop->Handle=GetDC(HWND_DESKTOP);
tbitmap->Width=Screen->Width;
tbitmap->Height=Screen->Height;
Canvas->CopyRect(Canvas->ClipRect,tDesktop,tDesktop->ClipRect);
tjpeg->Assign(tbitmap); //将图象转成JPG格式
tjpeg->SaveToStream(tmpStream); //将JPG图象写入流中
tjpeg->Free();
tmpStream->Position=0;
Socket->SendText(IntToStr(tmpStream->Size)); //发送图象大小
}
if (RevText=="OK")
{
tmpStream->Position=0;
Socket->SendStream(tmpStream); //发送JPG图象
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
ServerSocket1->Active=true;
}
//---------------------------------------------------------------------------

Client:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include "Jpeg.hpp"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TMemoryStream *tmpStream=new TMemoryStream;
long lC=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Button3Click(TObject *Sender)
{
try
{
ClientSocket1->Active=true;
}
catch(...)
{
ShowMessage("服务器连接出错!");
}

}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
ClientSocket1->Socket->SendText("'GetImage");//发送请求
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
TCustomWinSocket *Socket)
{
byte Buf[10000];
String L;
Graphics::TBitmap *tbitmap = new Graphics::TBitmap;
TJPEGImage * tjpeg=new TJPEGImage;
long len;
if (lC==0) //lC为服务端发送的字节数,如果为0表示为尚未开始图象接收
{
L=Socket->ReceiveText();
lC=StrToInt(L); //设置需接收的字节数
Socket->SendText("OK"); //通知服务端开始发送图象
}
else
{
//以下为图象数据接收部分
len=Socket->ReceiveLength(); //读出包长度
Socket->ReceiveBuf(Buf,len); //接收数据包并读入缓冲区内
tmpStream->Write(Buf,len); //追加入流M中
if (tmpStream->Size>=lC) //如果流长度大于或等于需接收的字节数,则接收完毕
{
tmpStream->Position=0;
try
{
tjpeg->LoadFromStream(tmpStream); //将流M中的数据读至JPG图像对象J中
tbitmap->Assign(tjpeg); //将JPG转为BMP
Image1->Picture->Bitmap->Assign(tbitmap); //分配给image1
}
__finally //以下为清除工作
{
tbitmap->Free();
tjpeg->Free();
Socket->Close();
tmpStream->Free();
lC=0;
}
}
}
}
//---------------------------------------------------------------------------
短歌如风 2002-06-25
  • 打赏
  • 举报
回复
我看了一下Delphi的源代码,不同的是它是分段发送的,每次发送4096字节。源代码如下:
(这个函数被SendStream调用,这时FSendStream就是你传给它的参数。
function TCustomWinSocket.SendStreamPiece: Boolean;
var
Buffer: array[0..4095] of Byte;
StartPos: Integer;
AmountInBuf: Integer;
AmountSent: Integer;
ErrorCode: Integer;

procedure DropStream;
begin
if FDropAfterSend then Disconnect(FSocket);
FDropAfterSend := False;
FSendStream.Free;
FSendStream := nil;
end;

begin
Lock;
try
Result := False;
if FSendStream <> nil then
begin
if (FSocket = INVALID_SOCKET) or (not FConnected) then exit;
while True do
begin
StartPos := FSendStream.Position;
AmountInBuf := FSendStream.Read(Buffer, SizeOf(Buffer));
if AmountInBuf > 0 then
begin
AmountSent := send(FSocket, Buffer, AmountInBuf, 0);
if AmountSent = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if ErrorCode <> WSAEWOULDBLOCK then
begin
Error(Self, eeSend, ErrorCode);
Disconnect(FSocket);
DropStream;
if FAsyncStyles <> [] then Abort;
Break;
end else
begin
FSendStream.Position := StartPos;
Break;
end;
end else if AmountInBuf > AmountSent then
FSendStream.Position := StartPos + AmountSent
else if FSendStream.Position = FSendStream.Size then
begin
DropStream;
Break;
end;
end else
begin
DropStream;
Break;
end;
end;
Result := True;
end;
finally
Unlock;
end;
end;
短歌如风 2002-06-25
  • 打赏
  • 举报
回复
SendStream并不是传送一个流对象,而是把流中的数据读出来传送过去。你在接收时应根据实际情况决定使用ReceiveBuf(一般情况)或ReceiveText(如果是文本)接收。
事实上SendStream方法相当于:
char * Buf;
int BufLen;
BufLen = AStream->Size();
Buf = new char [BufLen];
AStream -> Position = 0;
AStream -> Read(Buf,BufLen);
ClientSocket1->Socket->SendBuf(Buf,BufLen);
delete []Buf;
delete AStream;//注意这句,你的流将被SendBuf释放,你不要再去释放它。

13,873

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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