初学socket编程,自己写了一个简单的ctNonBlocking程序,想法是把sever发来的数据连接在一起,存储在array中,程序段如下
procedure TForm1.RemoteSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
temp: array [0..500] of byte;
length:integer;
i:integer;
begin length:=RemoteSocket.Socket.ReceiveLength;
RemoteSocket.Socket.ReceiveBuf(temp,length); for i:=msgIn_length to msgIn_length+length do
msgIn[i]:=temp[i-msgIn_length]; msgIn_length:=msgIn_length+length;//测验用的显示代码
for i:=0 to msgIn_lengthNow do
Memo.Lines.Add(Inttostr(msgIn[i]));
end;可是该段代码无法正常工作,当sever连续发送报文过来,在memo中只显示了第一报文的一部分~然后程序就卡住了~弹出错误。我分析是delphi执行速度不够快,第一段报文还没有保存显示完,第二段就发过来造成这种线程之间的错误。不知该如何解决这种问题~望高手指点。~如果我采用ctBlocking模式~我该如何知道server段有报文发过来呢?然后主动去读。还是说我应该不断读socket,读不到东西就代表server没有报文法给我??
procedure TForm1.RemoteSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
temp: array [0..500] of byte;
length:integer;
i:integer;
begin length:=RemoteSocket.Socket.ReceiveLength;
RemoteSocket.Socket.ReceiveBuf(temp,length); for i:=msgIn_length to msgIn_length+length do
msgIn[i]:=temp[i-msgIn_length]; msgIn_length:=msgIn_length+length;//测验用的显示代码
for i:=0 to msgIn_lengthNow do
Memo.Lines.Add(Inttostr(msgIn[i]));
end;可是该段代码无法正常工作,当sever连续发送报文过来,在memo中只显示了第一报文的一部分~然后程序就卡住了~弹出错误。我分析是delphi执行速度不够快,第一段报文还没有保存显示完,第二段就发过来造成这种线程之间的错误。不知该如何解决这种问题~望高手指点。~如果我采用ctBlocking模式~我该如何知道server段有报文发过来呢?然后主动去读。还是说我应该不断读socket,读不到东西就代表server没有报文法给我??
解决方案 »
- DBGridEh不显示滚动条
- Delphi写的Com在用Regsvr32注册时出现内存错误.会是什么原因呢?
- 平安夜散分
- ######任意钱数转换大写,开来帮忙啊!!¥¥¥¥¥¥
- 线程与数据库的问题
- 急!急!急!!!(如何把执行ADOSTOREDPROC后的返回值(数据集),存到文件或者是流中)
- 怎样得到DBGrid控件中数据行号,比如,单击鼠标到第三行,即得变量3 先谢过了!
- 大家好!我是delphi的初学者,请大家帮帮忙?
- 菜鸟提问
- 抢分问题, 快来啊, 会者不难, 分不多,但容易得, 本人一向诚实可信, 保证给分
- dbgrid选中的问题?在线及等!!!!!
- 关于TCollection和TCollectionItem的问题
temp: PByte;
begin
length := RemoteSocket.Socket.RecivieLength;
GetMem(temp,length);
RemoteSocket.Socket.ReceiveBuf..... FreeMem(temp)其它错误没看出来,好象只有这个地方有可能出错。
1,socket是从参数传入的,用RemoteSocket.Socket有错。
2,一定要取得Socket.ReceiveBuf的返回值,它才是实际读出的。
3,静态分配有限的temp空间没有问题。
4,一次OnRead事件处理中,最好应该多次ReceiveBuf直到读不出更多数据。
5,Socket.ReceiveLength的值不太可靠,最好别用。
[email protected]
大多数情况下是编制SOCKET程序的时候,对SOCKET的机制了解不够.
其实有些东西做起来也不难,
比如OnRead事件中,不要根据Socket.ReceiveLength作什么判断,
因为它的值不精确.就ReceiveBuf读,从它的返回值中即可取得可靠数据长度.
对于传几百M的文件,因为传输时间可能比较长,尽管TCP本身保证了不受IP丢包损失数据影响,
仍有可能链路断掉.
可以自定义一个协议.文件分块传,标识出文件名,文件块偏移,文件块长度.
如果你要传几百M的文件的话,那么最好采用阻塞式。这样比较容易处理。
Socket: TCustomWinSocket);
var
temp: array [0..500] of byte;
length:integer;
i:integer;
begin length := Socket.ReceiveLength;
Lenght := Socket.ReceiveBuf(temp,length); for i:=msgIn_length to msgIn_length+length do
msgIn[i]:=temp[i-msgIn_length]; msgIn_length:=msgIn_length+length;//测验用的显示代码
for i:=0 to msgIn_lengthNow do
Memo.Lines.Add(Inttostr(msgIn[i]));
end;
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls;type
TForm1 = class(TForm)
ClientSocket1: TClientSocket;
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
procedure Button1Click(Sender: TObject);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
FStr:String;
Fo:TStream;
procedure DisplayMsg(s:string);
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
s:string;
iSize:Integer;
begin
FSTr:='';
SetLength(s,3);
repeat
iSize:=Socket.ReceiveBuf(pchar(s)^,3);
if iSize>0 then
begin
SetLength(s,iSize);
Fo.Write(pchar(s)^,iSize);
FStr:=FSTr+s;
end
until (iSize<>3) or (iSize=-1);
DisplayMsg(FStr);
end;procedure TForm1.DisplayMsg(s: string);
begin
memo1.Lines.Add(s)
end;procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Active:=true;
end;procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Fo:=TFileStream.Create('d:\test.txt',FmCreate);
end;procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Fo.Free;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
ClientSocket1.Active:=false;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
Canvas.StretchDraw();
end;end.
主要是现在我们已经定义了我们自己通信的协议了,数据总大小是无法知道的,而
每次传4K,后来用Iris拦截数据包分析得到:
4k中的第一个IP包乱掉了.这种情况我们要求重新发送此包(自己定义的协议要求).
这样好了几包后,又会出现这种情况了.
所以现在的情况是想找到一个妥善的解决办法或者处理机制来保证数据包的传输.
IP包是少不了要丢失或错误的..这没关系.
你们自己定义的通信协议总不会直接就架在IP层的基础上吧?IP包的乱掉,可能会造成TCP上发的应用数据块延迟,造成误码的机率倒实在很小.在这儿用'包'这词,出现层次上的混淆,倒不如称为数据块.
你的意思把文件拆成4K左右的报文,一个报文一个报文的发?
呵.这样实现机制可以参照一下TCP实现的原理方面的.