各位老大帮忙看一下,为什么在多线程时,服务器端不能接收客户端发来的消息!!! 总提示: Stream write error ( 积分: 50 )

  • 主题发起人 一团火
  • 开始时间

一团火

Unregistered / Unconfirmed
GUEST, unregistred user!
Sever
=========================================================================
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls;

type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
Memo1: TMemo;
procedure ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
procedure ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TClientThread = Class(TServerClientThread)
Private
Public
Procedure ClientExecute; override;
End;

var
Form1: TForm1;
file_name:string;
implementation

{$R *.dfm}
Procedure TClientThread.ClientExecute;
Var
ReceiveBuffer : Array[0..4095] Of Char;
SocketStream : TWinSocketStream;
BytesRead : Integer;
F : TFileStream;
Begin

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 为什么在此接收,客户端发来的文件名,总是提示错误
//
form1.ServerSocket1.Socket.ReceiveText;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Randomize;
file_name:='c:/temp/'+'a'+inttostr(Random(10)); //暂时放了一个隋机数作为文件名
While Not Terminated And ClientSocket.Connected Do
Begin
try
SocketStream := TWinSocketStream.Create(ClientSocket, 60000);
F := TFileStream.Create(file_name, fmCreate);
try
FillChar(ReceiveBuffer, 10, 0);
If SocketStream.WaitForData(5000) Then
Repeat
BytesRead := SocketStream.Read(ReceiveBuffer,SizeOf(ReceiveBuffer));
if BytesRead = 0 then
ClientSocket.Close
Else
F.WriteBuffer(ReceiveBuffer, BytesRead);
Until Not SocketStream.WaitForData(2000);
finally
SocketStream.Free;
ClientSocket.Close;
f.Free;
end;
except
end;
End;
End;


procedure TForm1.ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
SocketThread := TClientThread.Create(False, ClientSocket);
end;
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
memo1.Lines.Add('断开连接!');
memo1.Lines.Add('-------------------');
end;

procedure TForm1.ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
memo1.Lines.Add('同意连接!');
end;

procedure TForm1.FormShow(Sender: TObject);
begin
if ServerSocket1.Active=false
then ServerSocket1.Open;

end;
end.
==============================================================================
client

=============================================================================
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ScktComp, ComCtrls;
type
TForm1 = class(TForm)
ClientSocket1: TClientSocket;
BitBtn1: TBitBtn;
OpenDialog1: TOpenDialog;
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
StatusBar1: TStatusBar;
Edit2: TEdit;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
fsize:int64;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
Var
s : TWinSocketStream;
f : TFileStream;
// fname:string;
begin
edit1.Text:=trim(edit1.Text);
ClientSocket1.Open;
s := TWinSocketStream.Create(ClientSocket1.Socket, 60000);
f := TFileStream.Create(edit1.Text, fmShareDenyWrite);

//告诉远程传输文件的大小和文件名
fsize:=f.Size;
ClientSocket1.Socket.SendText(Format('%d|%s', [f.Size, ExtractFileName(OpenDialog1.FileName)]));

Try
s.CopyFrom(f, fsize);
Finally
s.Free;
f.Free;
StatusBar1.SimpleText:='传输失败!';
ClientSocket1.Close;
End;
ClientSocket1.Close;
StatusBar1.SimpleText:='传输成功!';
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
edit1.Text:=OpenDialog1.FileName;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if ClientSocket1.Active
then ClientSocket1.Close;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
ClientSocket1.Socket.SendText('client send!');
edit1.Text:=clientsocket1.Socket.ReceiveText;
end;
end.
 
Sever
=========================================================================
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls;

type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
Memo1: TMemo;
procedure ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
procedure ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TClientThread = Class(TServerClientThread)
Private
Public
Procedure ClientExecute; override;
End;

var
Form1: TForm1;
file_name:string;
implementation

{$R *.dfm}
Procedure TClientThread.ClientExecute;
Var
ReceiveBuffer : Array[0..4095] Of Char;
SocketStream : TWinSocketStream;
BytesRead : Integer;
F : TFileStream;
Begin

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// 为什么在此接收,客户端发来的文件名,总是提示错误
//
form1.ServerSocket1.Socket.ReceiveText;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Randomize;
file_name:='c:/temp/'+'a'+inttostr(Random(10)); //暂时放了一个隋机数作为文件名
While Not Terminated And ClientSocket.Connected Do
Begin
try
SocketStream := TWinSocketStream.Create(ClientSocket, 60000);
F := TFileStream.Create(file_name, fmCreate);
try
FillChar(ReceiveBuffer, 10, 0);
If SocketStream.WaitForData(5000) Then
Repeat
BytesRead := SocketStream.Read(ReceiveBuffer,SizeOf(ReceiveBuffer));
if BytesRead = 0 then
ClientSocket.Close
Else
F.WriteBuffer(ReceiveBuffer, BytesRead);
Until Not SocketStream.WaitForData(2000);
finally
SocketStream.Free;
ClientSocket.Close;
f.Free;
end;
except
end;
End;
End;


procedure TForm1.ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
SocketThread := TClientThread.Create(False, ClientSocket);
end;
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
memo1.Lines.Add('断开连接!');
memo1.Lines.Add('-------------------');
end;

procedure TForm1.ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
memo1.Lines.Add('同意连接!');
end;

procedure TForm1.FormShow(Sender: TObject);
begin
if ServerSocket1.Active=false
then ServerSocket1.Open;

end;
end.
==============================================================================
client

=============================================================================
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ScktComp, ComCtrls;
type
TForm1 = class(TForm)
ClientSocket1: TClientSocket;
BitBtn1: TBitBtn;
OpenDialog1: TOpenDialog;
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
StatusBar1: TStatusBar;
Edit2: TEdit;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
fsize:int64;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
Var
s : TWinSocketStream;
f : TFileStream;
// fname:string;
begin
edit1.Text:=trim(edit1.Text);
ClientSocket1.Open;
s := TWinSocketStream.Create(ClientSocket1.Socket, 60000);
f := TFileStream.Create(edit1.Text, fmShareDenyWrite);

//告诉远程传输文件的大小和文件名
fsize:=f.Size;
ClientSocket1.Socket.SendText(Format('%d|%s', [f.Size, ExtractFileName(OpenDialog1.FileName)]));

Try
s.CopyFrom(f, fsize);
Finally
s.Free;
f.Free;
StatusBar1.SimpleText:='传输失败!';
ClientSocket1.Close;
End;
ClientSocket1.Close;
StatusBar1.SimpleText:='传输成功!';
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
edit1.Text:=OpenDialog1.FileName;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if ClientSocket1.Active
then ClientSocket1.Close;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
ClientSocket1.Socket.SendText('client send!');
edit1.Text:=clientsocket1.Socket.ReceiveText;
end;
end.
 
Receivetext 在阻塞模式下是读不出数据的

应该这样写:
var
Createfile: Boolean;
................
begin
.................
Createfile:= false;
SocketStream:= TWinSocketStream.Create(ClientSocket, 60000);
try
FillChar(ReceiveBuffer, SizeOf(ReceiveBuffer), 0);
BytesRead:= SocketStream.Read(ReceiveBuffer, SizeOf(ReceiveBuffer));
if BytesRead <> 0 then begin
if not Createfile then begin
file_name:= ..............;
F:= TFileStream.Create(file_name, fmCreate);
Createfile:= true;
end else begin
.............
end;
end else if Createfile then ClientSocket.Close;
.........................
 
To zhengdehei
你好,我没看太明白, 你是不是说在客户端 要把那个文件名,变成数据流 与 那个要发的文件流 合并在一起。 在服务器端,先收到这个数据流,然后分解出,文件名,再把那个分解后的文件流写成文件是吗?
可是我不知道具体如何来写,可以再帮帮我吗?[?]
===========================
只要是在这个多线程,的情况下,实现,客户端发,服务器端自动按原来的名,放在客户端指定的文件夹下就可以。[:(]
 
你顺序错了
你采用的是client 非阻塞模式,所以先 clientsocket.open
然后等待连接成功信息后,才能 SendText(文件信息),接着传输文件

在seversocket线程里先判断并建立文件,然后才开始接收流
 
顶部