⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stopwait.c

📁 在linux环境下模拟停止等待协议
💻 C
字号:
#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <signal.h>#include <time.h>#include <string.h>#if defined (__GNU_LIBRARY__)&& !defined (_SEM_SEMUN_UNDEFINED)#elseunion semun{	int val;	struct semid_ds *buf;	unsigned short int *array;	struct seminfo *__buf;};#endif#define SHMDATASIZE 1000#define BUFFERSIZE (SHMDATASIZE -sizeof(int))#define byte int8_t#define SEND 0#define  START 1#define FRAME 2#define SHARE 3int Semid,length;void delete (void);void sigdelete (int signum);void locksem (int semid,int semnum);void unlocksem (int semid,int semnum);void waitzero(int semid,int semnum);void write (int shmid,int semid,char *buffer);int mysemget (key_t kye,int nsems,int semflg);int mysemctl (int shmid,int semnum,int cmd,union semun arg);int mysemop (int semid,struct sembuf *sops,unsigned nsops);int myshmget (key_t key,int size,int shmflg);void *myshmat (int shmid,const void *shmaddr,int shmflg);int myshmctl (int shmid,int cmd,struct shmid_ds *buf);struct DataFrame  //数据帧{		byte PRE;	byte NS;	int DATA[80];	unsigned int FCS;	byte EOT;};struct AckFrame  //确认,否定帧{	byte PRE;	byte NR;	int ACK;	unsigned int FCS;	byte EOT;};int main (int argc,char *argv[]){	char selection[3],*buffer;	union semun sunion;
	int semid,shmid,length=10,j,k;
	void *shmdata;	struct DataFrame SendFrame[21],*send;	struct AckFrame ReceiveFrame,*receive;	pid_t pid1,pid2;
	semid=mysemget(IPC_PRIVATE,4,SHM_R|SHM_W);
	Semid=semid;
	//atexit(&delete);
	//signal(SIGINT,&sigdelete);

	sunion.val=1;
	mysemctl(semid,SEND,SETVAL,sunion);	mysemctl(semid,SHARE,SETVAL,sunion);
	sunion.val=0;	mysemctl(semid,FRAME,SETVAL,sunion);
	mysemctl(semid,START,SETVAL,sunion);	shmid=myshmget(IPC_PRIVATE,SHMDATASIZE,IPC_CREAT|SHM_R|SHM_W);	shmdata=myshmat(shmid,0,0);	*(int *)shmdata=0;	buffer=shmdata+sizeof(int);	buffer[0]='0';	buffer[1]='1';	//myshmctl(shmid,IPC_RMID,NULL);	//printf("请输入要传递的帧数(1~20):\n");	//scanf("%d",&length);	srand(time(NULL));	for(j=1;j<=length;j++)	{	  for(k=0;k<80;k++)	    SendFrame[j].DATA[k]=rand()%2;	  SendFrame[j].PRE=0x00;          SendFrame[j].EOT=0x04;	}	ReceiveFrame.PRE=0x00;	ReceiveFrame.EOT=0x04;	ReceiveFrame.ACK=1;	receive=shmdata+sizeof(int)+2*sizeof(char);	*receive=ReceiveFrame;
	pid1=fork();	//*********************************************************************核心代码************************************************************	if(pid1){//父进程,为发送方		int count=0;		char *temp;		int i,j,f=1;		while(count<=length&&f==1){			locksem(semid,SEND);	//等待SEND信号			locksem(semid,SHARE);	//获得进入共享内存的互斥信号量			temp=shmdata+sizeof(int);			receive=shmdata+sizeof(int)+2*sizeof(char);			ReceiveFrame=*receive;			if(  temp[0]=='0' && temp[1]=='1'   &&   ReceiveFrame.ACK==1  )count++;//如果是确认帧则发送下一帧,否则将上一个帧重发			*(int *)shmdata=count;			temp[0]=temp[1]='1';			send=shmdata+2*sizeof(char)+sizeof(int);			*send=SendFrame[count];			if(count>length){				printf("全部帧发送完毕!\n");								exit(0);			}			printf("**********************************发送进程**************************************\n");			printf("第%d帧发出,数据为:\n",count);			fflush(stdout);			for(j=0;j<80;j++){				printf("%d",SendFrame[count].DATA[j]);				fflush(stdout);			}			printf("\n**********************************发送进程**************************************\n\n\n");			unlocksem(semid,SHARE);	//释放进入共享内存的互斥信号量			unlocksem(semid,START);	//通知计时器可以开始计时			unlocksem(semid,FRAME);	//通知接受进程有帧到达			pid2=fork();			if(!pid2){	//父进程中的子进程,作为计时器用				locksem(semid,START);	//等待计时信号				sleep(3);	//计时3秒				locksem(semid,SHARE);	//获得进入共享内存的互斥信号量				temp=shmdata+sizeof(int);				if((*(int *)shmdata)==count && temp[0]=='1'){					temp[1]='0';					printf("**********************************计时器进程************************************\n");					printf("超时,要求发送进程重新发送!\n");					printf("**********************************计时器进程************************************\n\n\n\n\n");					unlocksem(semid,SHARE);	//释放进入共享内存的互斥信号量					unlocksem(semid,SEND);				}else{					unlocksem(semid,SHARE);	//释放进入共享内存的互斥信号量				}				f=0;	//标记位,使定时器进程计完时后自动结束			}		}	}else{	//子进程,即接受进程		while(1){			char *temp,selection[3];			int cou;			locksem(semid,FRAME);	//等待有数据帧到达			locksem(semid,SHARE);	//获得进入共享内存的互斥信号量			cou=*(int *)shmdata;			if(cou>length)break;			temp=shmdata+sizeof(int);			send=shmdata+sizeof(int)+2*sizeof(char);			SendFrame[0]=*send;			printf("**********************************接受进程**************************************\n");			printf("第%d帧到达,数据为:\n",cou);			fflush(stdout);			for(j=0;j<80;j++){				printf("%d",SendFrame[0].DATA[j]);				fflush(stdout);			}			printf("\n接受 1      /拒绝 2     /丢弃 3    ?\n");	//接受用户输入			fflush(stdout);			fgets (selection,sizeof (selection),stdin);			switch(selection[0]){				case '1': 	 if(temp[1]=='1'){                                                    	temp[0]='0';							receive=shmdata+sizeof(int)+2*sizeof(char);							ReceiveFrame.ACK=1;	//返回确认帧							*receive=ReceiveFrame;                                        	        unlocksem(semid,SHARE);	//释放进入共享内存的互斥信号量						       unlocksem(semid,SEND);                            			 }else{							  unlocksem(semid,SHARE);	//释放进入共享内存的互斥信号量						}                                 break;                               case '2':if(temp[1]=='1'){                                                     temp[0]='0';						     receive=shmdata+sizeof(int)+2*sizeof(char);					  	    ReceiveFrame.ACK=0;	//返回否认帧						    *receive=ReceiveFrame;                                                     unlocksem(semid,SHARE);	//释放进入共享内存的互斥信号量					            unlocksem(semid,SEND);                             			}else{							  unlocksem(semid,SHARE);	//释放进入共享内存的互斥信号量						}                             			  break;                               default:unlocksem(semid,SHARE);break;                    			}			printf("**********************************接受进程**************************************\n\n\n\n\n");		}	}	//*********************************************************************核心代码************************************************************	return 0;}


void delete(void){
	printf("\n quit;delete the semaphore %d \n",Semid);
	union semun sem;
	if(mysemctl(Semid,0,IPC_RMID,sem) == -1)	{
		printf("Error releasing semaphore. \n");
	}
}

void sigdelete(int signum){
	exit(0);
}

void locksem(int semid,int semnum){
	struct sembuf sb;

	sb.sem_num=semnum;
	sb.sem_op=-1;
	sb.sem_flg=SEM_UNDO;

	mysemop(semid,&sb,1);
}

void unlocksem(int semid,int semnum){
	struct sembuf sb;

	sb.sem_num=semnum;
	sb.sem_op=1;
	sb.sem_flg=SEM_UNDO;

	mysemop(semid,&sb,1);
}

void waitzero(int semid,int semnum){
	struct sembuf sb;

	sb.sem_num=semnum;
	sb.sem_op=0;
	sb.sem_flg=0;

	mysemop(semid,&sb,1);
}



int mysemget(key_t key,int nsems,int shmflg)	{
	int retval;
	retval=semget(key,nsems,shmflg);
	if(retval==-1)	{
		printf("semget key %d,nsems %d failed:%s",key,nsems,strerror(errno));
		exit(255);
	}
	return retval;
}

int mysemctl(int semid,int semnum,int cmd,union semun arg)	{
	int retval;
	retval=semctl(semid,semnum,cmd,arg);
	if(retval==-1)	{
		printf("semctl semid %d,semnum %d,cmd %d failed:%	s",semid,semnum,cmd,strerror(errno));
		exit(255);
	}
	return retval;
}

int mysemop(int semid,struct sembuf *sops,unsigned nsops)	{
	int retval;
	retval=semop(semid,sops,nsops);
	if(retval==-1)	{
		printf("semop semid %d (%d operations) failed:%s",semid,nsops,strerror(errno));
		exit(255);
	}
	return retval;
}

int myshmget(key_t key,int size,int shmflg)	{
	int retval;
	retval=shmget(key,size,shmflg);
	if(retval==-1)	{
		printf("shmget key %d,size %d failed:%s",key,size,strerror(errno));
		exit(255);
	}
	return retval;
}

void *myshmat(int shmid,const void *shmaddr,int shmflg)	{
	void *retval;
	retval=shmat(shmid,shmaddr,shmflg);
	if(retval==(void*)-1)	{
		printf("shmat shmid %d failed:%s",shmid,strerror(errno));
		exit(255);
	}
	return retval;
}

int myshmctl(int shmid,int cmd,struct shmid_ds *buf)	{
	int retval;
	retval=shmctl(shmid,cmd,buf);
	if(retval==-1)	{
		printf("shmctl shmid %d,cmd %d failed:%s",shmid,cmd,strerror(errno));
		exit(255);
	}
	return retval;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -