我现在想作一个屏幕监视软件,客户端直接读取一个jpg文件后,保存到流里面,然后,后 Internet面板最后那两个控件转输(ClientSocket 和 ServerSocket 控件,Delphi 7).**********************************************
**********客户端
var
nJpgSize:LongInt;
i,j,n:LongInt;
nCompletedSize:LongInt;
tempStream :TMemorystream;
begin
tempStream:=TMemoryStream.Create; JPGFile.LoadFromFile('c:\qq.jpg');
JPGFile.SaveToStream(JPGStream); nJpgSize:=JPGStream.Size;
showmessage('will send to server!' + inttostr(nJpgSize));
edtMsg.Lines.Add('取屏幕完毕!通知服务器接收数据!<size>' + inttostr(nJpgSize) ); JPGStream.Position :=0;
sendMessageOut('#SumSize=' + inttostr(nJpgSize));
sleep(300); if IsServer then
ServerSocket.Socket.Connections[0].SendStream(JPGStream)
else
ClientSocket.Socket.SendStream(JPGStream);
************************************
*********服务器端
procedure TChatForm.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
S:String;
FullFileStream:TStreamMemmory; //用于保存最终完整的图片文件流begin
FullFileStream:=TStreamMemmory.create(); edtMsg.Lines.Add ('Server Socket get new data!');
if IsStream =false then
begin
s:=Socket.ReceiveText;
Memo2.Lines.Add(S);
edtGet.Text :=S;
edtMsg.Lines.Add ('收到数据,但不是流!');
exit;
end; //**** 下面表示是流信息
nCurrStream_Len:=Socket.ReceiveLength;
edtMsg.Lines.Add ('Server Socket正在接收流信息[收到的大小' + inttostr(nCurrStream_Len) + ']nSumSize=' + inttostr(nSumSize));
Socket.ReceiveBuf(tempbuffer,nCurrStream_Len);
edtMsg.Lines.Add (' 把数据写入流中 '); TempStream.WriteBuffer (Mybuffer,nCurrStream_Len); //把数据写入流中 if CompletedSize < nSumSize then //CompletedSize:已接收数据 nSumSize:总数据 nCurrStream_Len:当前包的大小
begin
FullFileStream.Seek(CompletedSize,soFromBeginning); //如果不要这两行,则执行到 **here001时出错,且没有任何图像
FullFileStream.CopyFrom(TempStream,0); //如果要这两行,则能显示图像,但图像下半部份混乱,上半部份正常 CompletedSize := CompletedSize + nCurrStream_Len ;
end; if nCurrStream_Len >=nSumSize then //准备建立jpg
begin
TempStream.Position :=0; //,nCurrStream_Len
try
JPGFile.LoadFromStream(TempStream); // **here001
BitMap.Assign(JPGFile);
Image1.Picture.Bitmap.Assign(JPGFile);
refresh;
StatusBar1.Panels[0].Text :='显示图像......';
edtMsg.Lines.Add(#13 + '-------------');
edtMsg.Lines.Add(#13);
fmRemoteSRC.Image1 :=image1;
IsStream:=false;
if chkShowBigWindow.Checked then
showBigWindow();
finally
TempStream.Clear;
end;
end;end;
ClientSocket.socket.sendstream(JPGStream);
N:=JpGStream.Size; //假设为 8500
在服务器端用 ServerSocket 接收.
Var
Array buff [0..10000] :byte;
TempStream:TmemoryStream;
Begin
TempStream.Create; If 没有接收完毕 then
Begin
End; End;
******************************************
******************************************问题:
1、在服务器端接收的数据为什幺总是比实际转送前的数据多出几k 的大小(我在接收完毕后作了 TempStream.Size 的读取 )?
2、为什幺无法还原成JPG图片,在建立JPG时总是提示 error #54 或 #45 之头的错误 ?
3、上术代码应该如何改正?
4、有没有繁体或英文版本的邮件内容监视程序?要Free且注册的。( [email protected] 或 http://www.tanyong.com)谢谢各位!
**********客户端
var
nJpgSize:LongInt;
i,j,n:LongInt;
nCompletedSize:LongInt;
tempStream :TMemorystream;
begin
tempStream:=TMemoryStream.Create; JPGFile.LoadFromFile('c:\qq.jpg');
JPGFile.SaveToStream(JPGStream); nJpgSize:=JPGStream.Size;
showmessage('will send to server!' + inttostr(nJpgSize));
edtMsg.Lines.Add('取屏幕完毕!通知服务器接收数据!<size>' + inttostr(nJpgSize) ); JPGStream.Position :=0;
sendMessageOut('#SumSize=' + inttostr(nJpgSize));
sleep(300); if IsServer then
ServerSocket.Socket.Connections[0].SendStream(JPGStream)
else
ClientSocket.Socket.SendStream(JPGStream);
************************************
*********服务器端
procedure TChatForm.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
S:String;
FullFileStream:TStreamMemmory; //用于保存最终完整的图片文件流begin
FullFileStream:=TStreamMemmory.create(); edtMsg.Lines.Add ('Server Socket get new data!');
if IsStream =false then
begin
s:=Socket.ReceiveText;
Memo2.Lines.Add(S);
edtGet.Text :=S;
edtMsg.Lines.Add ('收到数据,但不是流!');
exit;
end; //**** 下面表示是流信息
nCurrStream_Len:=Socket.ReceiveLength;
edtMsg.Lines.Add ('Server Socket正在接收流信息[收到的大小' + inttostr(nCurrStream_Len) + ']nSumSize=' + inttostr(nSumSize));
Socket.ReceiveBuf(tempbuffer,nCurrStream_Len);
edtMsg.Lines.Add (' 把数据写入流中 '); TempStream.WriteBuffer (Mybuffer,nCurrStream_Len); //把数据写入流中 if CompletedSize < nSumSize then //CompletedSize:已接收数据 nSumSize:总数据 nCurrStream_Len:当前包的大小
begin
FullFileStream.Seek(CompletedSize,soFromBeginning); //如果不要这两行,则执行到 **here001时出错,且没有任何图像
FullFileStream.CopyFrom(TempStream,0); //如果要这两行,则能显示图像,但图像下半部份混乱,上半部份正常 CompletedSize := CompletedSize + nCurrStream_Len ;
end; if nCurrStream_Len >=nSumSize then //准备建立jpg
begin
TempStream.Position :=0; //,nCurrStream_Len
try
JPGFile.LoadFromStream(TempStream); // **here001
BitMap.Assign(JPGFile);
Image1.Picture.Bitmap.Assign(JPGFile);
refresh;
StatusBar1.Panels[0].Text :='显示图像......';
edtMsg.Lines.Add(#13 + '-------------');
edtMsg.Lines.Add(#13);
fmRemoteSRC.Image1 :=image1;
IsStream:=false;
if chkShowBigWindow.Checked then
showBigWindow();
finally
TempStream.Clear;
end;
end;end;
ClientSocket.socket.sendstream(JPGStream);
N:=JpGStream.Size; //假设为 8500
在服务器端用 ServerSocket 接收.
Var
Array buff [0..10000] :byte;
TempStream:TmemoryStream;
Begin
TempStream.Create; If 没有接收完毕 then
Begin
End; End;
******************************************
******************************************问题:
1、在服务器端接收的数据为什幺总是比实际转送前的数据多出几k 的大小(我在接收完毕后作了 TempStream.Size 的读取 )?
2、为什幺无法还原成JPG图片,在建立JPG时总是提示 error #54 或 #45 之头的错误 ?
3、上术代码应该如何改正?
4、有没有繁体或英文版本的邮件内容监视程序?要Free且注册的。( [email protected] 或 http://www.tanyong.com)谢谢各位!
下載請注意:文件裏面有一個 qq.jpg的圖片,把它放到 c:\ 再調試.因為後來我想直接把一個圖片作為流傳送以測試程序的正確性.請各位一定要幫幫我!!
2.因为接收数据不正常而导致JPEG文件头定义不准,所以前提是保证接收到的数据正常。
3.首先解决问题1
4.偶这没有。
================================
对于Socket.ReceiveBuf
在调用比如:
iLen:=Socket.ReceiveLength();//得到的可能是一个比较大的值,比如1450
而当调用iLen:=Socket.ReceiveBuf(buf,iLen)之后可能并没有接收到预接收的字节数,即可能小于1450,从而此时若仍然1450处理,那么就会数据失真,即多出很多数据,比如实际接收到的是1400,那么若后续丢弃了iLen的值,就可能多出了50个字节。Delphi代码就不多写了,现在贴一小段C++代码,其实原理上面Dephi和CBuilder没多差别,只是语法上的差别罢了。
//-----------------------------------------------------------
void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
TMemoryStream *tmpMem=new TMemoryStream();
try
{
int iReceiveLength=Socket->ReceiveLength();
tmpMem->SetSize(iReceiveLength);
iReceiveLength=Socket->ReceiveBuf(tmpMem->Memory,iReceiveLength);
tmpMem->SetSize(iReceiveLength);
tmpMem->Position=0;
BufferMem->Position=BufferMem->Size;
BufferMem->CopyFrom(tmpMem,iReceiveLength);
EnterCriticalSection(&pLockXY);
try
{
CheckReceive();
}
__finally
{
LeaveCriticalSection(&pLockXY);
}
}
__finally
{
tmpMem->Free();
}
}