0
点赞
收藏
分享

微信扫一扫

竞赛 机器视觉 opencv 深度学习 驾驶人脸疲劳检测系统 -python

双井暮色 2023-10-05 阅读 38
c语言

selectTcpSer.c:

#include <myhead.h>

#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__\n",__LINE__);\
perror(msg);\
}while(0)

#define PORT 8888

int keybroad_event(fd_set readfds)
{
char buf[128] = "";
int sendfd = -1;
bzero(buf,sizeof(buf));

int res = scanf("%d %s",&sendfd,buf);
while(getchar()!=10);
if(res != 2)
{
printf("input error,usage:sendfd string\n");
return -1;
}

if(sendfd <=2 || FD_ISSET(sendfd,&readfds) == 0)
{
printf("非法的文件描述符\n");
return -1;
}

if(send(sendfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
return -1;
}
printf("send success\n");

return 0;
}
int cliconnect_event(int sfd,struct sockaddr_in cliaddrs[],fd_set *preadfds,int *pmaxfd)
{
int newfd = -1; //客户端文件描述符
struct sockaddr_in cin; //用来存储客户端地址信息
socklen_t addrlen = sizeof(cin);

newfd = accept(sfd,(struct sockaddr*)&cin,
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s:%d]客户端连接成功,newfd = %d\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);

cliaddrs[newfd]=cin; //将客户端地址信息保存到数组中

FD_SET(newfd,preadfds); //将文件描述符添加到集合中

*pmaxfd = *pmaxfd > newfd ? *pmaxfd:newfd; //更新maxfd

return 0;
}
int clichange_event(int fd,struct sockaddr_in cliaddrs[],fd_set *preadfds,int *pmaxfd)
{
char buf[128] = "";
bzero(buf,sizeof(buf));

ssize_t ret = recv(fd,buf,sizeof(buf),0);
if(ret < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == ret)
{
printf("[%s:%d]客户端下线 fd = %d",\
inet_ntoa(cliaddrs[fd].sin_addr),ntohs(cliaddrs[fd].sin_port),fd);

close(fd);
FD_CLR(fd,preadfds);

while(FD_ISSET(*pmaxfd,preadfds) == 0 && *pmaxfd-->=0);

return 0;
}

printf("[%s:%d] newfd = %d:%s\n",\
inet_ntoa(cliaddrs[fd].sin_addr),ntohs(ntohs(cliaddrs[fd].sin_port)),fd,buf);

//发送
strcat(buf,">-<");
if(send(fd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
return -1;
}

printf("send success\n");

return 0;
}
int main(int argc, const char *argv[])
{
//判断输入合法性
if(argc < 2)
{
printf("input error,usage:./a.out ip\n");
return -1;
}

//创建流式套接字
int sfd;
if((sfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
ERR_MSG("socket");
return -1;
}
printf("socket success sfd = %d\n",sfd);

//允许端口快速复用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}

//填写地址信息结构体给bind使用
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(argv[1]);

//bind绑定地址信息,必须绑定
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");

//listen 将套接字转换成监听模式
if(listen(sfd,128) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("listen success\n");

//创建一个读集合
fd_set readfds,tempfds;

//清零
FD_ZERO(

//将文件描述符添加到集合中
FD_SET(0,
FD_SET(sfd,

int s_res = -1;
ssize_t res = -1;
int maxfd = sfd; //存储最大文件描述符

struct sockaddr_in cliaddrs[1024]; //记录客户端信息

while(1)
{
//用来额外备份,保证原先的集合不变
tempfds = readfds;
//实行IO多路复用
s_res = select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(s_res < 0)
{
ERR_MSG("select");
return -1;
}
else if(s_res == 0)
{
printf("timeout\n");
return -1;
}

//当有文件描述符准备就绪时,该集合中就会只剩下已经准备就绪的文件描述符
for(int i=0;i<=maxfd;i++)
{
if(FD_ISSET(i,&tempfds) == 0)
continue;

//运行到这说明集合内有这个文件描述符
if(0 == i)
{
//键盘输入事件
keybroad_event(readfds);
}else if(sfd == i)
{
//客户端连接事件
cliconnect_event(sfd,cliaddrs,&readfds,
}else{
//客户端交互事件
clichange_event(i,cliaddrs,&readfds,
}
}
}

//关闭套接字
if(close(sfd) < 0)
{
ERR_MSG("close");
return -1;
}

return 0;
}

效果图:

举报

相关推荐

0 条评论