客户 - 服务器餐厅模拟

时间:2014-01-18 09:58:16

标签: c

我正在使用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
}

4 个答案:

答案 0 :(得分:0)

你可能想在循环中尝试sleep()函数,它会做的是暂停你的程序很长时间,然后执行后面的语句。

sleep(30);

我想你想要的是什么。看看here了解有关睡眠的更多信息。

您的代码应该是:

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
    }
}

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

更新2:

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

here

/* 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;

答案 1 :(得分:0)

您可以使用线程等待30秒,并在线程返回时进行检查以找出所有客户端的首选食物。这个线程link会有所帮助。

答案 2 :(得分:0)

当你进入伪代码时

  t = time now

  start loop

  ... do stuff

  t2 = time now

  delta = t2 - t

  sleep (30 - delta % 30)

  end of loop

答案 3 :(得分:0)

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到3秒之间发送得太晚,因为处理收到的数据包需要0到N秒。这种时序变化称为“抖动”。

要修复“抖动”,您可以在等待时处理收到的数据包,以便处理这些接收数据包所花费的时间不会影响回复发送的时间。

在这种情况下,时间线如下所示:

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秒的周期,“略低于最大平均负荷”。我们在这里真正谈论的是服务器能够从偶尔的“略高于最大平均负载”期间快速恢复。

对于我的方法,服务器会尽快恢复。对于“睡眠()”方法,恢复需要更长的时间,导致延长的“滞后浪涌”。