问:
我编了个网吧管理程序,是通过一台主机(NT)来控制几台机器(Win98),
主机端用ServerSocket,客户端用ClientSocket,用的是非阻塞式方式通
信,在调试时一直没什么事,但在线路拥挤的网吧上运行,却常常出现一两
台机器无法控制的现象,一直查不出什么原因,经这几天研究一把,发现是
TCP的通信机制引起的,主机或者客户端发送的命令不会马上送出,而是粘
连几个命令发出,这样造成传送出去的命令无法设别,请问哪位大侠指点一
下,如何实现一旦把命令送出后就真正的送出,即如何强迫Tcp把缓冲区清
空送出数据?
你好,cyhan:
这阶段我正好用tclientsocket和tserversocket的ctnonblocking方式实现文件从
client->server的传输,但是也发现这个问题,因为我设计成client端每发一个包,
server端都要给一个响应是否成功,跟你的问题很类似,请问一下你的粘包问题怎么
解决,能不能也帮我解决一下,多谢!
const _bbs='send_file_test11'
每个包结构为16位包标识(固定为_bbs)+4位(如下)+包数据(长度不定)
client端发的包(其中vctosave,vdsaveinfo,vcfirstbuf,vclastbuf为必发的包)
vctosave:请求server端上传文件(无包数据)
vcsaveinfo:发送文件信息-》vcsaveinfo+包数据(文件名称|文件时间|文件大小)
vcfirstbuf:
头一个包-》包数据长度:如果文件大小<datalen,为文件大小,
如果文件大小>=datalen,为datalen长的文件流(datalen大小可配置)
vccommonbuf:中间的包-》包数据为datalen长的文件流
vclastbuf:最后的包-》包数据长度为剩余文件流大小
server端发的包
vsready:已准备好
vssaveinfook:存文件信息成功
vsfirstbufok:存第一个包成功
vscommonbufok:存中间包成功
vssaveok:上传文件成功
问题在于:
1。client端发送一个包后,怎么才能判断server端是否响应超时
2。client端发送一个包后,按造delphi的onread的原理,可能会激发
server端的多个onread事件,我怎么写server端的读数据的过程?
我的程序大概如下:
unit client;
tform1.button1onclick(...)
begin
client1.open;
end;
tform1.client1connect(...)
begin
socket.sendbuf(_bbs+vcsave,20);
end;
tform1.client1tread(...)
var
getbuf,sendbuf:array [1..datalen+20] of char;
len,sendsize:integer;
begin
len:=socket.receivebuf(getbuf,datalen+20);
sendsize:=0;
if len>=20 then
begin
处理包(存文件流,处理出响应包sendbuf,sendsize);
end;
if sendsize>0 then socket.sendbuf(sendbuf,sendsize);
end;
unit server;
tform1.server1read(...)
var
getbuf,sendbuf:array [1..datalen+20] of char;
len,sendsize:integer;
begin
len:=socket.receivebuf(getbuf,datalen+20);
sendsize:=0;
if (len>=20)and(copy(getbuf,1,20)=_bbs) then
//问题就出在这里,如果client端发了一个包,server端激发了三个onread
事件,这是不是判断len>=20不是行不通了,因为其实包还没收完整,要等待
三个onread事件后才能处理,但是却怎么知道还没后续onread事件,我知道
是可以通过加包头和包尾解决,但是应该如何编码,如果包内容里也包括该
标识又该如何解决,还有如果网络数据如果很慢(如只有5byte),这时本身
的_bbs可能就不能在一个onread事件中读完,又该如何判断?
begin
处理包(处理出sendbuf,sendsize);
end;
if sendsize>0 then socket.sendbuf(sendbuf,sendsize);
end;