【问题标题】:Homework - One Server serves multiple Clients with Semaphores and Shared Memory作业 - 一台服务器为多个客户端提供信号量和共享内存
【发布时间】:2011-01-22 20:31:02
【问题描述】:

大家好,我还有另一个作业问题。我必须编写一个客户端和一个服务器程序,以便服务器(具有共享内存和信号量)可以与客户端通信。客户端从标准输入获取数据并将其发送到服务器,服务器对其进行排序并将其发送回。问题是服务器必须为多个客户端提供服务,而我编写了它,因此它只能为一个客户端提供服务。如果有人能给我这样的思想推动如何实现这一目标,那就太好了。

这是我的客户:

Client

和服务器:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <errno.h>

#define SEMKEY1 6666
#define SEMKEY2 7777
#define SHMKEY  8888
#define HSIZE    128

union semun {
  int val;                   /*value for SETVAL*/
  struct semid_ds *buf;      /*buffer for IPC_STAT, IPC_SET*/
  unsigned short int *array; /*array for getall, setall*/
  struct seminfo *__buf;     /*buffer for IPC_INFO*/
};

int P(int semid){
  struct sembuf occupy;
  int res;

  occupy.sem_num  =  0;
  occupy.sem_op   = -1;
  occupy.sem_flg  =  0;
  res = semop(semid, &occupy, 1);
  if(res < 0){
    fprintf(stderr,"P() Failed");
    exit(1);
  }
  return res;  
}

int V(int semid){
  struct sembuf release;
  int res;
  release.sem_num  =  0;
  release.sem_op   =  1;
  release.sem_flg  =  0;

  res = semop(semid, &release, 1);
  if(res < 0){
    fprintf(stderr,"V() failed");
    exit(1);
  }
  return res;  
}

int getSem(int key){
  int semid;
  int errno;

  if((semid = semget(key, 1, 0)) < 0){
    fprintf(stderr, "getSem failed for key %d because %d \n ", key, errno);
    exit(1);    
  }
  return semid;
}

/*STRUCKT die fuer die SHARED MEMORY benutzt wird*/
typedef struct srtelem {
  long elem;
  int flg;
}SMSTRCKT;

int long_comp(const void *a, const void *b){
  const int *ai = (const int *) a;
  const int *bi = (const int *) b;

  return *ai - *bi; 
}

void print_hangar(long *hangar, int i){
  int j;

  for(j = 0; j < i; j++){
    printf("%ld \n", *(hangar+j));
  }
}

int main(){
  int semid1, semid2, shm_id, count;
  int errno, index;
  SMSTRCKT *shmptr;
  long hangar[HSIZE];

  /*Semaphore hollen*/
  semid1 = getSem(SEMKEY1);
  semid2 = getSem(SEMKEY2);
  count = 0;
  index = 0;
  printf("\t**SERVER**\n");

  /*Shared memory anlegen*/
  if((shm_id = shmget(SHMKEY, sizeof(SMSTRCKT), 066)) < 0){
    fprintf(stderr, "SHMGET failed because of %d\n",errno);
    exit(1);  
  }

  /*Shared memory anhaengen*/
  if((shmptr = (SMSTRCKT *) shmat(shm_id, NULL, 0)) == (SMSTRCKT*) -1){
    fprintf(stderr,"SHMAT failed because of %d\n", errno);
    exit(1);    
  }

/*Get date from the Client*/
   while((shmptr->flg) == 1){
      P(semid2);
      if(shmptr->flg != 0){
    printf("elem %d \n ",(int) shmptr->elem);
    *(hangar+count) = shmptr->elem;
    count++;
      }  
      V(semid1);
    }
    qsort(hangar,count, sizeof(long),long_comp);

    /*Send the result to the Client*/
    while(index < count){
      P(semid1);

      shmptr->elem = *(hangar+index);
      /*printf(" elem %ld  index %d\n", shmptr->elem, index);*/
      ++index;

      V(semid2);
    }

    P(semid1);
    shmptr->flg++;
    V(semid2);

  return 0;
}

【问题讨论】:

  • 尝试使用制表键或至少 4 个空格进行缩进
  • Extra-push:停下来想想你为什么要使用信号量。如果只有一个客户,那有什么意义呢?信号量是一个棘手的概念,拥有两个或更多客户端(或两个或更多服务器)确实会迫使您了解它们的工作原理。
  • @Andy,不, 在 SO 编辑器中使用 Tab 键(除非您希望代码的缩进混乱)。请只留空格。
  • @Robin,我从您的代码中删除了大量空行和注释行(使其缩短了约 50%),并根据 SO 标准对其进行了格式化。请下次自己修剪 - 您发布的代码越长,有人真正阅读它的机会就越少。此外,不要使用 &lt;pre&gt;&lt;code&gt; 标签 - 只需将代码缩进 4 个空格,或使用编辑器中的 {} 按钮。
  • @Peter:谢谢你的帮助,我会的。 @aqua:信号量的存在是为了防止一个进程在另一个进程已经在使用它时访问临界区中的某些东西。在我的示例中,不要让客户端在空闲之前访问共享内存(未被其他客户端或服务器使用)

标签: c concurrency semaphore shared-memory


【解决方案1】:

首先,您需要了解信号量和互斥量,它们将在多线程应用程序中使用,所以我想您需要创建一个服务于多个客户端但使用线程等信号量的服务器。

您需要自己了解信号量 + 互斥锁的工作原理和工作原理以及它们的区别,稍后您会发现很多有关使用多线程的服务器的示例,并且会指出如何修改当前服务器。

小教程: http://www.csc.villanova.edu/~mdamian/threads/posixsem.html

还有 2 个例子: http://www.minek.com/files/unix_examples/semab.html http://refactormycode.com/codes/1237-using-semaphores-in-c-and-forking-processes

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多