客户端服务器餐厅模拟



我正在用C语言中的select()制作一个模拟快餐或其他东西的客户端服务器。

我有客户在1-5之间随机点了一份"食物"。服务员每隔30秒就决定所有客户最喜欢的食物是什么。他为这些客户提供服务,他们会关闭连接,而对于其他客户,他会给他们发一条等待的信息。没有得到服务的客户再尝试两次,否则他们就会离开。

我的问题是,如何让服务器每30秒检查一次。他们的订单是什么?

我试着制作一个数组,但我不知道如何让服务器每30秒连续"检查"一次,然后将数组设置为0。

这是伪代码:

**client**
patience=0;served=0;
do
{send random 1-5
receieve message. if 1->served=1; if 0, patience++;
}while patience !=3 and served!=1;
if served==1 send -1
else send -2
close connection
**Server**
while(1)
{
serves clients in a concurent manner
select
adds client in socket list
serves client

waits message
if 1-5 adds in vector
//here I don't know how to make it wait for 30 sec.
//If I put sleep(30), it's going to sleep for each client every time. I want it to permanently check every 30 sec and send messages to clients.
send respones(0 or 1, depending on if the max order is the same as the client's)
if -1, thanks for the food
if -2, going somewhere else
close client connection
}

您可能想在循环中尝试sleep()函数,它将使程序暂停那么长时间,然后执行下面的语句。

sleep(30);

我想这就是你想要的。看看这里了解更多关于睡眠的信息。

您的代码应该是:

for(i=0; i<=100; i++)//Checks 100 times
{
sleep(30);
checkserverforupdate();
}

更新代码:

while(1){//runs infinite times
sleep(30);//pauses here for 30 seconds everytime before/after running the following code
*client**
patience=0;served=0;
do
{send random 1-5
receieve message. if 1->served=1; if 0, patience++;
}while patience !=3 and served!=1;
if served==1 send -1
else send -2
close connection
**Server**
while(1)
{
serves clients in a concurent manner
select
adds client in socket list
serves client

waits message
if 1-5 adds in vector
//here I don't know how to make it wait for 30 sec.
//If I put sleep(30), it's going to sleep for each client every time. I want it to permanently check every 30 sec and send messages to clients.
send respones(0 or 1, depending on if the max order is the same as the client's)
if -1, thanks for the food
if -2, going somewhere else
close client connection
}
}

看看sleep(30)会发生什么,程序会暂停30秒,然后执行之后写的代码,如果你把它放在while循环中,它每次都会等待。

更新2:

如何在C:中获取当前时间的代码

此处

/* localtime example */
#include <stdio.h>
#include <time.h>
int main ()
{
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
printf ( "Current local time and date: %s", asctime (timeinfo) );
return 0;
}

更新3:所以你的代码应该是这样的:

time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
printf ( "Current local time and date: %s", asctime (timeinfo) );

All of your code here
and then get the time again,
time_t rawtime1;
.....
and then you may calculate the difference between them and put a sleep statement as you wish. If the time you want it to pause is in x then,
sleep(x);
return 0;

您可以使用线程等待30秒,当线程返回时,进行检查,从所有客户端中找出首选食物。此线程链接将有所帮助。

当你进入伪代码时,这里是

t = time now
start loop
... do stuff
t2 = time now
delta = t2 - t
sleep (30 - delta % 30)
end of loop

C中的select()函数有一个超时参数。正确的逻辑应该是:

nextTime = now() + 30 seconds;
while(running) {
currentTime = now();
if( nextTime <= currentTime() ) {
makeFood();
nextTime += 30 seconds;
} else {
timeout = nextTime - currentTime;
if(select(..., timeout) > 0) {
// Check FD sets here
}
}
}

编辑(添加解释如下)

你必须有某种数据结构来跟踪这种状态(例如,哪些客户要求吃哪些食物)。上面没有显示此数据结构。

// Check FD sets部分修改当前状态。例如,当一个新客户点了一些食物时,你可以将详细信息添加到等待点餐的客户的链接列表中。当客户厌倦了等待时,你会将他们的订单从等待订单的客户列表中删除。

makeFood()函数将查看(先前存储的)状态,并确定要制作哪种类型的食物;然后通知客户继续等待或他们的食物已经做好(并将收到食物的客户赶走)。

编辑2-使用sleep()的问题

如果你一直睡到合适的时间发送回复,然后接收数据包,然后发送回复;那么接收数据包所需的时间会有所不同(取决于接收到的数据包数量),这意味着发送回复的时间会有变化(取决于收到的数据包的数量)。

时间线可能是这样的:

12:00:59  - stop sleeping
12:00:59  - check for received packets and find there's none
12:00:59  - do 1 second of processing
12:01:00  - start sending reply packets
12:01:02  - finish sending reply packets
12:01:02  - sleep for the remaining 27 seconds
12:01:29  - stop sleeping
12:01:29  - check for received packets and find there's lots of them
12:01:29  - process received packets for 3 seconds
12:00:33  - do 1 second of processing (3 seconds too late)
12:01:34  - start sending reply packets (3 seconds too late)
12:01:02  - finish sending reply packets (3 seconds too late)
12:01:02  - sleep for the remaining 24 seconds

在这种情况下,由于处理接收到的数据包需要0到N秒,所以在0到3秒之间发送回复太晚了。这种定时变化被称为"抖动"。

为了修复"抖动",您可以在等待时处理接收到的数据包,这样处理这些接收到的信息包所花费的时间就不会影响发送回复的时间。

在这种情况下,时间线看起来是这样的:

12:00:59  - stop waiting and receiving packets
12:00:59  - do 1 second of processing
12:01:00  - start sending reply packets
12:01:02  - finish sending reply packets
12:01:02  - receive packets while waiting for the remaining 27 seconds
12:01:29  - stop waiting and receiving packets
12:00:29  - do 1 second of processing
12:01:00  - start sending reply packets
12:01:02  - finish sending reply packets
12:01:02  - receive packets while waiting for the remaining 27 seconds

在这种情况下,回复总是在正确的时间发送。

编辑3-使用sleep()的另一个问题

睡眠的第一个问题是因为无法提前预测理想的睡眠时间,这会导致你醒得太晚(这会导致"抖动")。第二个问题是,这只会影响服务器处理"几乎最大负载"时期的能力。

基本上,你睡得太久,随着负荷的增加,你会睡得太长,没有足够的时间来处理你在等待时应该收到的负荷。

当存在恒定的"几乎最大负载"时,这会导致振荡。例如,如果有足够的负载,需要29秒才能完成所有操作(接收数据包、处理数据包和发送回复数据包);然后在一段30秒的时间里,你睡得太久,没有及时处理负荷,完成得太晚;然后你意识到你需要睡"负秒"(但你不能让时间倒流——你能做的最好的事情就是跳过sleep())。这将多余的负载推到下一个30秒的时间段上。经过几次(多次)这样的"跳过睡眠但仍然开始得太晚"的30秒后,你终于赶上了;一旦发生这种情况,你就会再次睡得太久,然后重新开始整个事情。

当然,这是假设存在恒定的"几乎最大负载"。现实生活几乎从来都不是这样。在实践中,你往往会出现波动——例如,一个30秒的周期"略高于最大平均负荷",然后是一个30秒内"略低于最大平均负荷"。我们在这里真正谈论的是服务器从偶尔的"略高于最大平均负载"时期快速恢复的能力。

对于我的方法,服务器会尽快恢复。对于"sleep()"方法,它需要更长的时间才能恢复,从而导致长时间的"滞后浪涌"。

最新更新