Blue
Red
Green
Orange
Voilet
Slate
Dark

!!!高难度问题:线程当中的Socket发送和时间的不确定性问题!!!(300分)

L

liaotw

Unregistered / Unconfirmed
GUEST, unregistred user!
我在一个线程当中有一个专门的发送函数以发送本线程的缓冲池中的数据。函数的源代码
在下面。
该函数内部包含有延时代码,根据该代码的延时,可以看到,该函数的实际执行时间应该在
62ms左右,但是在实际的运行当中,该函数绝大多数的执行时间在140ms左右。
注意的是:该线程还有另外一个函数用以供其他线程调用,以向缓冲池填写发送的数据。(经
测试,这个函数虽然在本线程当中,但是其执行时间却在其他线程当中,因此该接收函数的
执行不会影响发送函数的执行时间)。
求解决方案或者就该现象进行分析。
我的函数代码如下:

{
const
FSendCyc = 62
SEND_PACKAGE_LEN = 256
}
procedure TSocketThread.SendData;
label
Re;
var
Ret : Integer;
begin
try
if FSendAble then begin
Re:
if SendFlag then begin
//经测试,极少发生Socket异常,因此在Case语句当中的可以不进行考虑时间延迟
if send(FActiveSocket,FSendBufPoolA[0], 256,0) = SOCKET_ERROR then begin
Ret := WSAGetLastError;
case Ret of
WSAEWOULDBLOCK : //现在发送过程被阻塞,需要等待一会儿在进行连接。
begin
Sleep(FSendCyc);
Goto Re;
end;
else
begin
frmMain.SaveLog(1, '头端忙,向头端发送CA数据包时被拒绝, 网络返回编码是:'+IntToStr(Ret));

FSendAble := false;
FConnected := false;
CloseSocket(FActiveSocket); //关闭Socket
end;
end; //end case
end;
offsetA := 0;
SendFlag := False;
end else begin
//经测试,极少发生Socket异常,因此在Case语句当中的可以不进行考虑时间延迟
if send(FActiveSocket,FSendBufPoolB[0], 256,0) = SOCKET_ERROR then begin
Ret := WSAGetLastError;
case Ret of
WSAEWOULDBLOCK : //现在发送过程被阻塞,需要等待一会儿在进行连接。
begin
Sleep(FSendCyc);
Goto Re;
end;
else
begin
frmMain.SaveLog(1, '头端忙,向头端发送CA数据包时被拒绝, 网络返回编码是:'+IntToStr(Ret));

FSendAble := false;
FConnected := false;
CloseSocket(FActiveSocket); //关闭Socket
end;
end;
end;
offsetB := 0;
SendFlag := True;
end;

inc(FSendNO);

//睡眠指定的周期------------------------------------
te := GetTickCount;
if (te - ts) < FSendCyc then begin
Sleep(FSendCyc - (te - ts));
end;
ts := GetTickCount;
//经反复测试,函数执行到这里,显示共消耗70ms
end; //end if FSendAble then begin---------------------------------------
//经反复测试,函数执行到这里,显示共消耗70ms
except
raise;
end;
end;
//经反复测试,函数执行到这里,大多数时候显示共消耗140ms到200ms
 
L

liaotw

Unregistered / Unconfirmed
GUEST, unregistred user!
怎么没有人回答啊?
 

张无忌

Unregistered / Unconfirmed
GUEST, unregistred user!
这很正常,TCP在默认设置下延时比较长,那是为了提高发送效率,
但是你可以修改他的设置就可以提高响应时间,但是发送效率就要降低
 

张无忌

Unregistered / Unconfirmed
GUEST, unregistred user!
去掉Nagle算法就可以降低发送延时。。。
TCP有很多控制发送速率的算法,如果禁用Nagle算法可能要出一些问题
 
L

liaotw

Unregistered / Unconfirmed
GUEST, unregistred user!
您说的有一些道理,但是还没有完全分析出来吧。
各位高手,继续分析啊!
 
B

barton

Unregistered / Unconfirmed
GUEST, unregistred user!
1.没搞明白楼主的意思。你计算线程运行时间的方法并不正确呀!两个GetTickCount之间的
差值只能算出两个时间之间的差值,但这个时间内100%还有其它线程占用过CPU的。
2.楼主代码风格极差。一是用标签不是万不得已不好用,二是两个发送池的代码几乎一样,
居然写成两块。做成一块就行了。将缓冲池作为参数传入。如果你是用来作为同步过程使用
就更离谱了。相当于你把关键的步骤放到主线程中运行了,你这个线程还有什么用处。
3.既然你线程中有供别的线程使用的方法,一定是与你本线程有相同对象的操作你才这样做
的。从代码分析是共享了缓冲池这个数组,你必须保证这个数据同时只能被一个线程操作。
但你保证不了。你不知道你的线程到底在什么地方被挂起,什么地方被唤醒,你的所有的操
作都不是原子化的。除非你在操作缓冲池数组的时候用了CriticalSection锁定。
 
L

liaotw

Unregistered / Unconfirmed
GUEST, unregistred user!
不好意思,我已经解决这个问题了。
我这段代码的确存在许多可以改进的地方,多谢指教啦!
对于Barton的指教,非常感谢。不过您的第一点是错误的,取时间的函数和线程是无关的;对于第三点,则我们想的是一样的。
对于第二点,则有考虑的余地啦,因为这样程序代码执行效率是最高的啦,不过的确不好看。
 
顶部 底部