#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <poll.h>
int main(int argc, char const *argv[])
{
if (argc != 2)
{
perror("请输入端口号\n");
return -1;
}
int sockfd,acceptfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (socket < 0)
{
perror("socket err");
return -1;
}
printf("socket ok %d\n", sockfd);
struct sockaddr_in serveraddr, caddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[1]));
serveraddr.sin_addr.s_addr = INADDR_ANY;
socklen_t len = sizeof(caddr);
if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind err");
return -1;
}
printf("bind ok \n");
if (listen(sockfd, 6) < 0)
{
perror("listen err");
return -1;
}
printf("listen ok \n");
//
struct pollfd fds[20]={};//创建struct类型的文件描述符组,
//填充组里边的数据
fds[0].fd=0;//填写需要使用的文件
fds[0].events=POLLIN;//设置检测事件为读事件
//填充数据,类型同上
fds[1].fd=sockfd;
fds[1].events=POLLIN;
//
int ret;
int n = 2;//文件描述符的个数,用于判断
char buf[128];
int recvbyte;
while (1)//循环poll检测,poll阻塞等待有事件产生返回 -1
{
//阻塞,没有信号就不会进入循环
ret=poll(fds,n,-1);
if (ret<0)
{
perror("poll err\n");
return -1;
}
for (int i = 0; i <n; i++)//循环监听
{
if (fds[i].revents == POLLIN)
{
if (fds[i].fd==0)//监听到描述符等于0执行
{
fgets(buf,sizeof(buf),stdin);
printf("key:%s\n",buf);
for (int j = 2; j < n; j++)
{
send(fds[j].fd,buf,sizeof(buf),0);
}
}
else if (fds[i].fd == sockfd)//监听sockfd
{
acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
if (acceptfd<0)
{
perror("accept err\n");
return -1;
}
printf("accept ok\n");
printf("ip:%s ,post:%d\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));
fds[n].fd=acceptfd;//添加文件描述符,如果继续有人来链接,也可以监听到
fds[n].events=POLLIN;//设置状态
n++;
}
else
{
recvbyte = recv(fds[i].fd,buf,sizeof(buf),0);
if (recvbyte<0)
{
perror("recv err\n");
return -1;
}
else if (recvbyte == 0)
{
printf("%d client exit\n",fds[i].fd);
close(fds[i].fd);
fds[i]=fds[n-1];//客户端退出,文件描述符减少,文件描述符向前位移,执行前要先关闭
n--;//减去多余的位置
i--;
break;
}
else
{
printf("%d buf:%s\n",fds[i].fd,buf);
}
}
}
}
}
close(sockfd);
return 0;
}
重要的事说三遍,循环监听文件描述符,循环监听文件描述符,循环监听文件描述符