TCP/IP高手请进!分不成问题!谢谢(100分)

  • 主题发起人 主题发起人 ForCode
  • 开始时间 开始时间
F

ForCode

Unregistered / Unconfirmed
GUEST, unregistred user!
  我的目的是想用TServerSocket和TClientSocket在两个计算机上相互传输文本及比较大的文
件。
TClientSocket向TServerSocket发文本指令分别以'1''2''3''4'开头在TServerSocket
的ClientRead中判断收到的文本第一个字符也就是取出'1''2''3''4'分别响应不同的程序,
同时向TClientSocket发送对应的响应,如果是'3'开头将接收一个3M的文件。如果在
TClientSocket的OnRead事件中如果收到服务器发来'4'的响应将接收一个服务传输过来的文
件。没说太明白,其实就是两端相互任意的发送文本和比较大的文件。但总是出现错误,请
高手指点迷津,本人将不对感激
 
看一下FTP协议
 
我详细代码如下:发送数据部分
你可以接受端先发送一个请求,比如 GET FILENAME 发送端如果同意就发送OK*12345(文件大小)
如果不同意就发送(ERROR),接受端接到OK和文件大小后再发送一个OK,这个时候发送端就可以发
送数据。
我的代码如下:测试过,没有什么问题,错误保护自己加上就性了
接受部分
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<iSize do
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;
 
对于比较大的的文件,要分成一段一段发送。
 
使用indy的IdTcpServer,IdTcpclient比较好。
 
接受部分(有个用户和密码check,你取消就可以)
procedure TTCP_Server.IdTCPServerExecute(AThread: TIdPeerThread);
var
FStream : TFileStream;
FileName : String;
CmdStr : String;
begin
CmdStr :=AThread.Connection.ReadLn();
if CompareStr(Copy(CmdStr,1,6),'<SEND>')=0 then
begin //1
Delete(CmdStr,1,6);
Cmd := '上传文件';
FileName := CmdStr;
if FileExists(ExtractFilePath(Application.ExeName)+FileName) then
DeleteFile(ExtractFilePath(Application.ExeName)+FileName);
try
FStream := TFileStream.Create(ExtractFilePath(Application.ExeName)+FileName,FmCreate);
AThread.Connection.ReadStream(FStream,2048,true);
Finally
FStream.Free;
AThread.Connection.Disconnect;
end;
end //1
else if CompareStr(Copy(CmdStr,1,6),'<AGET>')=0 then
begin //2
Delete(CmdStr,1,6);
Cmd := '下载文件';
FileName := CmdStr;
if FileExists(ExtractFilePath(Application.ExeName)+FileName) then
begin
try
FStream := TFileStream.Create(ExtractFilePath(Application.ExeName)+FileName,FmOpenRead);
AThread.Connection.WriteStream(FStream,True,False);
Finally
FStream.Free;
AThread.Connection.Disconnect;
end;
end
else
begin
AThread.Connection.WriteLn('Failed');
AThread.Connection.Disconnect;
end;
end //2
else if CompareStr(Copy(CmdStr,1,6),'<USER>')=0 then
begin //3
Delete(CmdStr,1,6);
User := UpperCase(Trim(DecryptString(CmdStr,20504))); //CmdStr;
if CompareStr(User,'XDM')=0 then
begin
Memo1.Lines.Add('User: '+User);
CmdStr :='';
end
else
begin
Memo1.Lines.Add('User: '+User+' 非法登陆,已关闭连接');
CmdStr := '';
AThread.Connection.WriteLn('<Failed>');
AThread.Connection.Disconnect;
end;
end //3
else if CompareStr(Copy(CmdStr,1,6),'<PASS>')=0 then
begin //4
Delete(CmdStr,1,6);
Password := DecryptString(CmdStr,20504); //CmdStr;
if CompareStr(Password,'123abc')=0 then
begin
Memo1.Lines.Add('Login..........Accepted');
Memo1.Lines.Add('Connected......'+DateTimeToStr(Now));
CmdStr := '';
AThread.Connection.WriteLn('<Accepted>');
end
else
begin
Memo1.Lines.Add('Password Wrong...Login Failure');
AThread.Connection.WriteLn('<Failed>');
CmdStr :='';
AThread.Connection.Disconnect;
end;
end; //4
end;

主要发送部分
procedure TTCP_Client.BtnSendClick(Sender: TObject);
var
FStream : TFileStream;
begin
if IdTcpClient.Connected then begin
IdTcpClient.WriteLn('<SEND>'+ExtractFileName(FileName));
if FileName = '' then
MessageBox(Handle,'没有选择文件','Error',MB_OK)
else begin
try
FStream := TFileStream.Create(FileName,FmOpenRead);
FStream.Position := 0;
FStream.Seek(0,0);
IdTcpClient.WriteStream(FStream,true,false);
Finally
FStream.Free;
IdTcpClient.Disconnect;
end;
Memo1.Lines.Add('Transferred OK');
end;
end
else
begin
MessageBox(Handle,'没有连接服务器','Error',MB_Ok);
end;
end;
 
我也遇到过同样问题,结果是我拆的包太大造成的错误.
我每次发送4000k,就没问题.你试一试缩小每次发包的长度.
如果还不行,把原码贴出来.大家一起找错误
 
老夫已经完成一次传输多个文件的小程序,也是用TServerSocket和TClientSocket,非常简单!只需要
用Socket.sendbuff()就可以了,管他什么各式的文件。关键在于一问一答机制,直到文件结尾,然后
再同样传输下一个文件。
 
TO 胖的:
我上面的代码考虑了拆包问题。。。。不用分包 [:D]
我认为用阻塞式实现最好,不用考虑包大小问题,
而且效率很高,很容易实现多线程
 
To kofxdm,
Indy的确挺好用,我也在用,但有些觉得挺有用的属性,确不知道怎么用!
如:IdTCPServer控件的自动回应功能(出错回应等)
还有连接数的设置,超出连接数回应等等
不知道你有没有对IdTcpServer全面了解呢?能说说这些是如何使用的吗?谢谢!

 
连接数我是在这里面处理的:
procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
i:=i+1;
Label1.Caption:=inttostr(i);
end;
 
楼主,
是传送命令出错(不能分辨出'1'什么的)呢????
还是传送文件时出错呀?????

你贴点你的关键代码出来吧!!!
这样比较好解决问题点!!!
以上的老兄们也贴了很好的代码啦,看看吧!!!
呵呵`~~~~~~~~~~~~~~~~
 
后退
顶部