关于ClientSocket1通信的问题(急!!!!在线等待) (300分)

  • 主题发起人 主题发起人 wxpub
  • 开始时间 开始时间
W

wxpub

Unregistered / Unconfirmed
GUEST, unregistred user!
发送图片文件
发送格式要求'Jpg_J01|jpg文件名|'+文件
说明:strCondition='Jpg_J01|文件名|'
filename=文件路径/文件名
var
JpgBuff,PCondition:Pchar;
JpgFile:TmemoryStream;
size,len:integer;
begin
len:=length(strCondition);
PCondition:= pchar(strCondition);
JpgFile:= TmemoryStream.Create;
JpgFile.LoadFromFile(filename);
getmem(JpgBuff,JpgFile.Size+len);
JpgFile.Position:=0;
JpgFile.WriteBuffer(PCondition,len);
JpgFile.Read(JpgBuff^,JpgFile.Size);
size:=JpgFile.Size;
ClientSocket1.Socket.SendBuf(JpgBuff[0],size);
//请问能否转换为string类型,如何转换。
ClientSocket1.Socket.Sendtext();
end;
 
你不是已经写好了吗?
 
还是帮你提提吧,顺便给点分
 
但是服务器端不能接收到!
 
请确定
clientsocket的Host应当是接收方的IP地址
Port应当是接收方侦听端口号
 
这些都没问题。我发送字符串服务端可接收到
如:ClientSocket1.Socket.SendBuf('fsdfdsafdafasf');
 
把你要发送的文件先读入一个流,再把这个文件分包发送,每次的包不要超过1.5K,建议是
1K,这个东西我刚做完,用我的方法可以实现传送任何文件
 
还有对于大文件必须进行分割
 
我的文件小于400k,要求一次发送
下面的测试事例发送接收成功,但对其修改为所提问题的方式后,对应的服务器端不能接收
unit ss;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp, ExtCtrls, Buttons;
type
TForm1 = class(TForm)
bt1: TButton;
sss: TServerSocket;
cs: TClientSocket;
Edit1: TEdit;
Edit2: TEdit;
Button1: TButton;
BitBtn1: TBitBtn;
procedure bt1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure csRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button1Click(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
ss,S1:TmemoryStream;
size,sizei:integer;
ms:TCustomWinSocket;
public
AA:PCHAR;
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.bt1Click(Sender: TObject);
var
sv:pchar;
f,d:Pchar;
i,j:integer;
begin

ss:= TmemoryStream.Create;
ss.LoadFromFile('c:/a.jpg');
ss.Position:=0;
getmem(f,ss.Size);
ss.Read(f^,ss.Size);
size:=ss.Size;
showmessage(inttostr(size));
i:=0;
sss.Socket.Connections[0].SendBuf(f[0],size);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
//sss.Service:='192.131.0.185';
//sss.Port:=9999;
sss.Active:=true;
//cs.Active:=true;
s1:=TmemoryStream.Create;
end;

procedure TForm1.csRead(Sender: TObject;
Socket: TCustomWinSocket);
var
p:Pchar;
i,j,k:integer;
begin
K:=9894;
j:=0;
i:=0;
getmem(p,k);
while (j<9894) do
begin
i := Socket.ReceiveBuf(p[j],k);
if i<0 then
break;
j:=j+i;
k:=k-i;
end;
s1.Write(p[0],9894);
s1.SaveToFile('c:/ry.jpg');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
p:Pchar;
i,j:integer;
begin
getmem(p,607912);
i:=ms.ReceiveBuf(p[0],607912);
if i<>607912 then
begin
j:=i;
i:=607912-i;
i:=ms.ReceiveBuf(p[j],i);
end;

s1.Write(p^,607912);
s1.SaveToFile('c:/m.jpg');
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
cs.Address:=edit1.Text;
cs.Port:=strtoint(edit2.Text);
cs.Active:=true;
end;

end.
 
大文件最好是分割成小块再发送,另外你上面的代码也是有问题的,
JpgFile.WriteBuffer(PCondition,len);
//覆盖了原数据的一部分而不是插入
 
一些例子:
//别人的tcpclient 例子
张无忌 (2003-02-10 14:08:00)
procedure TForm1.ClientSocket2Read(Sender: TObject;
Socket: TCustomWinSocket);
var len:integer;
temp:string;
begin
if stStatue=stgetFile then
begin
Len:=Socket.ReceiveLength;
Temp:=Socket.ReceiveText;
filem.Write(PChar(Temp)^,len);
//filem是一个文件流
inc(allLen,len);
if allLen=getfilesize then
//allLen是文件长度,你先传送过来
ShowMessage('文件接受完毕!');

end;

发送部分
const
MAX_LEN=2048;
var
iSen:integer;
//iSen发送出去的长度
iSize:integer;
//文件长度 最好是全局变量
buf:array[1..MAXLEN]of char;
senlen:integer;
//每次应该发送的长度
ret:integer;
//实际发送的文件长度
filen:TFileStream;
//最好是全局变量
iSen:=0;
while iSen<iSizedo

begin
FillChar(buf,MAX_LEN,0);
if iSize-iSen>MAX_LEN then
senlen:=MAX_LEN
else
senLen:=iSize-iSen;
filen.Position:=iSen;
filen.Read(buf,senLen);
ret:=ClientSocket1.Socket.SendBuf(buf,senLen);
inc(iSen,ret);
end;

//others
可将文件分割后发送,发送端的代码如下:
var
FileFrom,FileTo,Send,Temp:String;
MemStr:TMemoryStream;
SendTimes,i:Integer;
SendState:String;
Socket:TCustomWinSocket;
const SckMaxDataLength:Integer=2048;
begin

MemStr:=TMemoryStream.Create;
MemStr.LoadFromFile(FileFrom);
SetString(Send,PChar(MemStr.Memory),MemStr.Size);
if Length(Send) mod SckMaxDataLength=0 then
SendTimes:=0
else
SendTimes:=1;
Inc(SendTimes,Length(Send) div SckMaxDataLength);
for i:=0 to SendTimes-1do
begin
if i=0 then
SendState:='0'//只有一个包
else
if i=SendTimes-1 then
SendState:='2'//后面还有包
else
SendState:='1';//最后一个包
Temp:=Format('%s%s',[SendState,Copy(Send,i*SckMaxDataLength+1,SckMaxDataLength)]);
Socket.SendText(Temp);
end;

MemStr.Free;
end;

吃饭去也,接收端的自己写吧。
//


duducat (2002-05-24 16:33:00)
下程序可以传递任意大小文件,如果不符合,可以不要给我加分哟:)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ScktComp;
type
TCon = record
FileName : String;
TotalSize : Integer;
Status : Integer;
end;

PCON = ^TCON;
TForm1 = class(TForm)
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
ClientSocket: TClientSocket;
ServerSocket: TServerSocket;
btnServerActive: TButton;
btnClientCon: TButton;
btnClientDisConn: TButton;
BtnClientSendF: TButton;
Memo1: TMemo;
OpenDialog: TOpenDialog;
Edit1: TEdit;
Label1: TLabel;
procedure btnClientConClick(Sender: TObject);
procedure btnClientDisConnClick(Sender: TObject);
procedure BtnClientSendFClick(Sender: TObject);
procedure ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
procedure btnServerActiveClick(Sender: TObject);
procedure ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.DFM}
var Count : Integer;
function GetFileSize(const FileName: string):integer;
var f : TFileStream;
begin
f := TFileStream.Create(FileName,fmOpenRead or fmShareDenyNone);
Result :=f.Size;
F.Free;
end;

procedure TForm1.btnClientConClick(Sender: TObject);
begin
ClientSocket.Active := True;
with OpenDialogdo
begin
Execute;
if FileName <> '' then
begin
Edit1.Text := 'UPLOAD '+ ExtractFileName(FileName) +' '+Inttostr(GetFileSize(FileName));
Label1.Caption := FileName;
ClientSocket.Socket.SendText(edit1.Text);
end;
end;
end;

procedure TForm1.btnClientDisConnClick(Sender: TObject);
begin
ClientSocket.Active := False;
end;

procedure TForm1.BtnClientSendFClick(Sender: TObject);
var fs : TFileStream;
Buf : pointer;
begin
fs := TFileStream.Create(Label1.Caption ,fmOpenRead or fmShareDenyNone);
GetMem(Buf,fs.Size);
fs.Seek(0,soFrombegin
ning);
fs.ReadBuffer(Buf^,fs.Size);
memo1.Lines.Add('has send : '+inttostr(ClientSocket.Socket.SendBuf(Buf^,fs.Size)));
end;

procedure TForm1.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.add(socket.ReceiveText);
end;

procedure TForm1.ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ErrorCode := 0;
end;

procedure TForm1.btnServerActiveClick(Sender: TObject);
begin
ServerSocket.Active := True;
end;

procedure TForm1.ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var c : pcon;
begin
c :=new(pcon);
c.FileName := '';
c.TotalSize := 0 ;
c.Status := 0;
Socket.Data := c;
Socket.SendText('已经连接,请输入UPLOAD FILENAME SIZE'#13#10);
end;

procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var C : PCON;
cmd:String;
Buffer : pointer;
nRetr : integer;
fs : TFileStream;
const bufferSize = 1024 ;
begin
C:= Socket.Data ;
case c.Status of
0 :
begin
cmd := trim(Socket.ReceiveText) ;
if Pos('UPLOAD ',uppercase(cmd)) > 0 then
begin
c.FileName := trim(Copy(cmd,Pos(' ',cmd)+1,Length(cmd)));
c.TotalSize := StrToInt(Copy(c.FileName,Pos(' ',c.FileName)+1,Length(c.FileName)));
c.FileName := trim(Copy(c.FileName,1,Pos(' ',c.FileName)));
c.Status := 1;
Socket.Data := C;
Socket.SendText('you can send File !'#13#10);
end;
end;
1 :
begin
Count := count + 1;
GetMem(Buffer,BufferSize);
nRetr := Socket.ReceiveBuf(Buffer^,BufferSize);
Memo1.Lines.Add(IntToStr(Count) + ' ' + IntToStr(nRetr));
if not FIleExists('c:/'+c.FileName) then
begin
fs :=TFileStream.Create('c:/'+c.FileName,fmCreate or fmShareDenyNone);
fs.Seek(0,soFrombegin
ning);
end
else
begin
fs :=TFileStream.Create('c:/'+c.FileName,fmOpenWrite or fmShareDenyNone);
fs.Seek(0,soFromEnd);
end;
fs.WriteBuffer(Buffer^,nRetr);
fs.Destroy;
FreeMem(Buffer);
end;
end;
end;

procedure TForm1.ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ErrorCode := 0;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Count := 0;
end;

procedure TForm1.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
ClientSocket.Active := False;
ServerSocket.Active := False;
end;
end.


kuangwenwei (2002-05-24 17:55:00)
至duducat
你的这段代码好象只能在局域网内传输,
在INTERNET上传输就有问题了,比如在一个局域网内的某台机器向
另外一个局域网的某台机器传输文件时,将无法联接。
如果你已经成功联接了的话,请问客户端的IP及端口要怎样设置?

duducat (2002-05-24 18:09:00)
to kuangwenwei
好的,我再看看!!!其实原理一样的

张无忌 (2002-05-24 18:41:00)
2个系统都在不同的局域网内,是无法用TCP建立连接,除非通过第3方代理中转!

//
YoungSun (2002-08-01 10:41:00)
传输多媒体文件和普通文件有什么区别吗?[?]
传输单个文件的方法
原理说明:发送方首先发送文件大小,接收方创建一个Stream,准备接收,发送准备好信息,
发送方发送整个流,如果流比较大,系统会自动分包发送,所以在客户端要做一个拼接处
理。即判断接收后的Stream的大小,如果小于文件大小,则继续接收,否则接收完成。
//********************************************************
private
stream : TMemoryStream;
//定义内存流,其实用文件流也可以
size,count : integer;
//文件大小
end;

implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Address := Edit1.Text;
ClientSocket1.Active := True;
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := 'Connected to '+Socket.RemoteAddress;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
stream := TMemoryStream.Create;
if OpenDialog1.Execute then
begin
stream.LoadFromFile(OpenDialog1.FileName);
size := stream.Size;
//获得文件大小
count := 0;
ClientSocket1.Socket.SendText(inttostr(size));
//先发送大小
end;
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
rcvtxt : string;
buf : array [1..2048] of char;
left : integer;
begin
rcvtxt := Socket.ReceiveText;
left := size - count;
//未读字节数
if AnsiPos('go',rcvtxt)=1 then
//收到响应则发
begin
if sizeof(buf)<left then
//若满一块则读一块
begin
stream.Read(buf,sizeof(buf));
Socket.SendBuf(buf,sizeof(buf));
count := count + sizeof(buf);
end
else
//不满则发剩余的
begin
stream.Read(buf,left);
Socket.SendBuf(buf,left);
end;
end;
end;

Server端(收方)

private
Tof : file;
size,count :integer;
end;

var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.CutFirst(denstr: string;scrstr: string);
var
len :integer;
begin
len := length(scrstr);
denstr := copy(scrstr,2,(len-1));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
ServerSocket1.Active := True;
StatusBar1.SimpleText := 'Listening...';
end;

procedure TForm1.ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := 'Connected from '+ Socket.RemoteAddress;
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
buf : array [1..2048] of char;
rcvtxt : string;
left,len : integer;
begin
len := Socket.ReceiveLength;
if len<10 then
//若长度小于10则认为是文件长度
begin
rcvtxt := Socket.ReceiveText;
size := strtoint(rcvtxt);
count := 0;
if SaveDialog1.Execute then
begin
AssignFile(ToF, SaveDialog1.FileName);
Rewrite(ToF, 1);
end;
Socket.SendText('go');
//响应一块
end
else
begin
left := size - count;
//未写的字节数
if sizeof(buf)<left then
//满一块则写一块
begin
Socket.ReceiveBuf(buf,sizeof(buf));
BlockWrite(Tof,buf,sizeof(buf));
count := count + sizeof(buf);
Socket.SendText('go');
end
else
//否则写剩余字节数
begin
Socket.ReceiveBuf(buf,left);
BlockWrite(Tof,buf,left);
CloseFile(Tof);
end;
end;
end;
注:代码是转贴别人的。

//
 
请问如何处理!
 
pihome:
你说的有问题哟,不会覆盖原来的部分的,当你在一个流的最后追加后,指针自动指向最后
 
请问可通过什么方法的转换用sendtext()发送?
 
用INDY试试吧
 
JpgFile.Position:=0;
//先移到最前再写数据,当然是覆盖了
JpgFile.WriteBuffer(PCondition,len);
 
这个问题以前很多,看看以前的帖子吧。图象不用分割,系统给你分好了。
 
var
JpgBuff,PCondition:Pchar;
Stream:TmemoryStream;
size,len:integer;
begin
len:=length(strCondition);
PCondition:= pchar(strCondition);
Stream:= TmemoryStream.Create;
try
Stream.LoadFromFile(filename);
Size:=Stream.Size;

getmem(JpgBuff,Stream.Size+len);
try
Move(PCondition[0],JpgBuff[0],Len);
Move(Stream.Memory^,JpgBuff[Len],Stream.Size);
ClientSocket1.Socket.SendBuf(JpgBuff[0],Size+Len);
finally
FreeMem(JpgBuff,Size+Len);
end;
finally
Stream.Free;
end;
end;
 
to : smokingroom
可否转换为string,如何转换。
 
buf可以解决的话非要换成string吗?
那你把jpgbuff换成string就可以了,本来是pchar型,string(jpgbuff)
 
后退
顶部