数据中继select模型
数据中继select模型
示例:relay_select.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/select.h>
#define FILE1 "/dev/tty10"
#define FILE2 "/dev/tty11"
#define BUFFSIZE 1024
enum fsmstate //状态
{
STATE_R,
STATE_W,
STATE_AUTO,
STATE_EX,
STATE_T
};
struct fsm_st //状态机结构体
{
enum fsmstate state;
int sfd;
int dfd;
int lenth;
int pos;
char *err;
char buff[BUFFSIZE];
};
static void fsm_driver(struct fsm_st *fsm) //状态机
{
int ret;
switch(fsm->state) //状态判断及切换
{
case STATE_R: //读状态
fsm->lenth = read(fsm->sfd,fsm->buff,BUFFSIZE);
if(fsm->lenth<0)
{
if(errno == EAGAIN)
fsm->state = STATE_R;
else
{
fsm->err = "read";
fsm->state = STATE_EX;
}
}
else if(fsm->lenth == 0)
fsm->state = STATE_T;
else
{
fsm->pos =0;
fsm->state = STATE_W;
}
break;
case STATE_W: //写状态
ret = write(fsm->dfd,fsm->buff + fsm->pos,fsm->lenth);
if(ret <0)
{
if(errno == EAGAIN)
fsm->state = STATE_W;
else
{
fsm->err = "write";
fsm->state = STATE_EX;
}
}
else
{
fsm->pos +=ret;
fsm->lenth -=ret;
if(fsm->lenth ==0)
fsm->state = STATE_R;
fsm->state = STATE_W;
}
break;
case STATE_EX: //出错状态
fprintf(stderr,"%s\n",fsm->err);
fsm->state = STATE_T;
break;
case STATE_T: //结束状态
break;
default:
abort();
break;
}
}
static int max(int a,int b)
{
if(a > b)
return a;
return b;
}
static void relay(int fd1, int fd2) //状态机初始化及调用
{
struct fsm_st fsm12,fsm21;
int fd1_save,fd2_save;
fd_set rfds,wfds; //文件集合
fd1_save = fcntl(fd1,F_GETFL);
fsm12.state = STATE_R;
fsm12.sfd = fd1;
fsm12.dfd = fd2;
fd2_save = fcntl(fd2,F_GETFL);
fsm21.state = STATE_R;
fsm21.sfd = fd2;
fsm21.dfd = fd1;
while(fsm12.state != STATE_T || fsm21.state != STATE_T)
{
FD_ZERO(&rfds); //select监视文件设置
FD_ZERO(&wfds);
if(fsm12.state == STATE_R)
FD_SET(fsm12.sfd,&rfds);
if(fsm12.state == STATE_W)
FD_SET(fsm12.dfd,&wfds);
if(fsm21.state == STATE_R)
FD_SET(fsm21.sfd,&rfds);
if(fsm21.state == STATE_W)
FD_SET(fsm21.dfd,&wfds);
if(fsm12.state <STATE_AUTO || fsm21.state <STATE_AUTO)
{
if(select(max(fd1,fd2)+1,&rfds,&wfds,NULL,NULL)<0) //监视可读、可写文件
{
if(errno == EINTR)
continue;
perror("select()");
exit(1);
}
}
if(FD_ISSET(fd1,&rfds) || FD_ISSET(fd2,&wfds) || fsm12.state > STATE_AUTO || fsm21.state >STATE_AUTO) //查看结果
fsm_driver(&fsm12);
if(FD_ISSET(fd2,&rfds) || FD_ISSET(fd1,&wfds) || fsm12.state > STATE_AUTO || fsm21.state >STATE_AUTO)
fsm_driver(&fsm21);
}
fcntl(fd1,F_SETFL,fd1_save);
fcntl(fd2,F_SETFL,fd2_save);
}
int main()
{
int fd1,fd2;
fd1 = open(FILE1,O_RDWR|O_NONBLOCK); //非阻塞形式打开
if(fd1 <0)
{
perror("open()");
exit(1);
}
fd2 = open(FILE2,O_RDWR|O_NONBLOCK); //非阻塞形式打开
if(fd2 <0)
{
perror("open()");
exit(1);
}
relay(fd1,fd2); //调用状态机
while(1)
pause(); //等待信号结束
close(fd1);
close(fd2);
exit(0);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现