我在server端和client端都使用Filestream來發送和接收文件,文件可以接收,文件大小一樣(右擊文件,查看屬性,接收文件的大小包括括號裡的位元組和來源文件的也一字不差),但文件的圖標卻是DOS執行文件的圖標,雙擊該文件後提示:
'c:\test.exe僅完成部分的readprocessmemory或writeprocessmemory要求.'
請問會是什麼原因造成的?如何解決?
我在接收完文件後有Filestream.Free;
還有奇怪的是當服務端和客戶端都在自已機子上運行時卻可正常打開文件.
'c:\test.exe僅完成部分的readprocessmemory或writeprocessmemory要求.'
請問會是什麼原因造成的?如何解決?
我在接收完文件後有Filestream.Free;
還有奇怪的是當服務端和客戶端都在自已機子上運行時卻可正常打開文件.
煩請幫我看看,謝謝.
主要代碼如下:
client端:
rcv := Socket.ReceiveText;
left := filesize - count;
if AnsiPos('go~',rcv)=1 then
begin
if sizeof(buf2)<left then
begin
fs.Read(buf2,sizeof(buf2)); //fs=filestream
Socket.SendBuf(buf2,sizeof(buf2));
count := count + sizeof(buf2);
end
else
begin
fs.Read(buf2,left);
Socket.SendBuf(buf2,left);
fs.Free;
end;server端:
len:=socket.ReceiveLength;
if len<8 then
begin
rcv:=socket.ReceiveText;
filesize:=strtoint(rcv);
count:=0;
socket.SendText('go~');
end
else
begin
left:=filesize-count;
if sizeof(buf2)<left then
begin
socket.ReceiveBuf(buf2,sizeof(buf2));
fs.Write(buf2,sizeof(buf2)); //fs=filestream
count:=count+sizeof(buf2);
socket.SendText('go~');
end
else
begin
socket.ReceiveBuf(buf2,left);
fs.Write(buf2,left);
fs.free;
socket.Close;
end;
end;
但最明显的错误是这句.你没有判断返回值.这个方法的返回值是实际接收的字节数.
不要理解成想去接收sizeof (buf2)这么大的数据就能读到.socket.ReceiveBuf(buf2,sizeof(buf2));
---------------
服务器端
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls;type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
Button1: TButton;
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
FS: TFileStream;implementation{$R *.dfm}procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
Buf: array [0..1023] of Byte;
iRecv: Integer;
begin
iRecv := Socket.ReceiveBuf(Buf, SizeOf(Buf));//iRecv是每次实际接收到的字节数
FS.Write(Buf, iRecv);//隐含了每次Write后FS的当前位置都会到FS结尾
end;procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
FileName: string;
begin
FileName := 'C:\a.ttt';
if FileExists(FileName) then DeleteFile(FileName);
FS := TFileStream.Create(FileName, fmCreate);
end;procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
FS.Free;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
ServerSocket1.Open;
end;end.
--------------
客户端
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp;type
TForm1 = class(TForm)
ClientSocket1: TClientSocket;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
FS: TFileStream;
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Open;
FS := TFileStream.Create('C:\aaa.bin', fmOpenRead);
end;procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Socket.SendStream(FS);
end;procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
FS.Free;
end;end.
实际上在ScktComp.pas单元可看源码.
function TCustomWinSocket.SendStreamPiece: Boolean;其源码简化了就是这样: 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
.....
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
传完结束break;
end;
end
end;
發送用sendstream,接收用
socket.receive(buf,len);
filestream.write(buf,len);
........
...........
可否再請教一個小問題:
用此方法有沒有傳送文件大小的限制?
我試過傳送30MB的文件,一切正常.
下面改进有信心了