#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <ctype.h>
#include <poll.h> //poll头文件
#define MAXSIZE 1024
#define IP_ADDR "127.0.0.1"
#define IP_PORT 8888
int main()
{
int i_listenfd, i_connfd;
struct sockaddr_in st_sersock;
char msg[MAXSIZE];
int nrecvSize = 0;
int index = 0; //记录fd数组中最大fd对应的下标
struct pollfd pofds[MAXSIZE]; //结构体数组
for (n : pofds) //将所有数组中的fd设为-1,方便以后填充
{
n.fd = -1;
}
if ((i_listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) //建立socket套接字
{
printf("socket Error: %s (errno: %d)\n", strerror(errno), errno);
exit(0);
}
memset(&st_sersock, 0, sizeof(st_sersock));
st_sersock.sin_family = AF_INET; //IPv4协议
st_sersock.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY转换过来就是0.0.0.0,泛指本机的意思,也就是表示本机的所有IP,因为有些机子不止一块网卡,多网卡的情况下,这个就表示所有网卡ip地址的意思。
st_sersock.sin_port = htons(IP_PORT);
if (bind(i_listenfd, (struct sockaddr *)&st_sersock, sizeof(st_sersock)) < 0) //将套接字绑定IP和端口用于监听
{
printf("bind Error: %s (errno: %d)\n", strerror(errno), errno);
exit(0);
}
if (listen(i_listenfd, 20) < 0) //设定可同时排队的客户端最大连接个数
{
printf("listen Error: %s (errno: %d)\n", strerror(errno), errno);
exit(0);
}
printf("listen fd: %d\n", i_listenfd);
pofds[index].fd = i_listenfd; //先赋值
pofds[index].events = POLLIN;
printf("======waiting for client's request======\n");
//准备接受客户端连接
while (1)
{
int nCount = poll(pofds, index + 1, -1); //阻塞监听
printf("----------poll监听到可读事件计数:%d\n", nCount);
for (int i = 0; i < MAXSIZE; i++)
{
if (nCount == 0)
{
break;
}
if (!(pofds[i].revents & POLLIN))
{
continue; //不在监听事件中则跳过
}
printf("----------即将处理监听到的 pofds[%d]: %d\n", i, pofds[i].fd);
nCount--; //每处理一次就自减1
if (pofds[i].fd == i_listenfd) //监听到有客户端连接
{
if ((i_connfd = accept(i_listenfd, (struct sockaddr *)NULL, NULL)) < 0) //阻塞等待客户端连接
{
printf("accept Error: %s (errno: %d)\n", strerror(errno), errno);
// continue;
}
else
{
printf("Client[%d], welcome!\n", i_connfd);
}
for (int n = 0; n < MAXSIZE; n++)
{
if (pofds[n].fd == -1) //将新客户端fd加入数组中
{
pofds[n].fd = i_connfd;
pofds[n].events = POLLIN;
index < n ? index = n : true;
printf("将新客户端fd加入数组中. fd:%d, index:%d\n", pofds[n].fd, index);
break;
}
}
}
else //监听到已连接的客户端发来的数据
{
//接受客户端发来的消息并作处理(小写转大写)后回写给客户端
memset(msg, 0, sizeof(msg));
if ((nrecvSize = read(pofds[i].fd, msg, MAXSIZE)) < 0)
{
printf("accept Error: %s (errno: %d)\n", strerror(errno), errno);
continue;
}
else if (nrecvSize == 0) //read返回0代表对方已close断开连接。
{
printf("client has disconnected!\n");
if (index == i) //如果是最大的下标的客户端退出,则index-1
{
index--;
}
pofds[i].fd = -1; //清除数组中相应位置
close(pofds[i].fd);
continue;
}
else
{
printf("recvMsg:%s", msg);
for (int i = 0; msg[i] != '\0'; i++)
{
msg[i] = toupper(msg[i]);
}
if (write(pofds[i].fd, msg, strlen(msg) + 1) < 0)
{
printf("accept Error: %s (errno: %d)\n", strerror(errno), errno);
}
}
}
}
} //while
close(i_listenfd);
return 0;
}