#ifndef UTILITY_H_INCLUDED
#define UTILITY_H_INCLUDED
#include <iostream>
#include <list>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
// clients_list save all the clients‘s socket
list<int> clients_list;//存储服务端的在线客户
/********************** macro defintion **************************/
// server ip
#define SERVER_IP "127.0.0.1"//使用本机环路测试地址作为连接socket绑定的ip地址
// server port
#define SERVER_PORT 8888//使用8888作为连接socket绑定的端口
//epoll size
#define EPOLL_SIZE 5000//epoll事件表最大事件数量
//message buffer size
#define BUF_SIZE 0xFFFF//读写缓冲最大值
#define SERVER_WELCOME "Welcome you join to the chat room! Your chat ID is: Client #%d"
#define SERVER_MESSAGE "ClientID %d say >> %s"
// exit
#define EXIT "EXIT"
#define CAUTION "There is only one int the char room!"
/********************** some function **************************/
/**
* @param sockfd: socket descriptor
* @return 0
**/
int setnonblocking(int sockfd)//将文件描述符设为非阻塞
{
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)| O_NONBLOCK);
return 0;
}
/**
* @param epollfd: epoll handle
* @param fd: socket descriptor
* @param enable_et : enable_et = true, epoll use ET; otherwise LT
**/
void addfd( int epollfd, int fd, bool enable_et )//将感兴趣的fd挂到epollfd指向的事件表
{
struct epoll_event ev;
ev.data.fd = fd;
ev.events = EPOLLIN;
if( enable_et )
ev.events = EPOLLIN | EPOLLET;
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
setnonblocking(fd);
printf("fd added to epoll!\n\n");
}
/**
* @param clientfd: socket descriptor
* @return : len
**/
int sendBroadcastmessage(int clientfd)//广播消息
{
// buf[BUF_SIZE] receive new chat message
// message[BUF_SIZE] save format message
char buf[BUF_SIZE], message[BUF_SIZE];
bzero(buf, BUF_SIZE);
bzero(message, BUF_SIZE);
// receive message
printf("read from client(clientID = %d)\n", clientfd);
int len = recv(clientfd, buf, BUF_SIZE, 0);//接收clientfd号聊天室的数据
if(len == 0) // len = 0 means the client closed connection
{
close(clientfd);
clients_list.remove(clientfd); //server remove the client
printf("ClientID = %d closed.\n now there are %d client in the char room\n", clientfd, (int)clients_list.size());
}
else //broadcast message
{
if(clients_list.size() == 1) { // this means There is only one int the char room
send(clientfd, CAUTION, strlen(CAUTION), 0);
return len;
}
// format message to broadcast
sprintf(message, SERVER_MESSAGE, clientfd, buf);//SERVER_MESSAGE="ClientID %d say >> %s",以此格式把数据发送給所有聊天室
list<int>::iterator it;
for(it = clients_list.begin(); it != clients_list.end(); ++it) {//遍历所有聊天室,向它们发送数据,除了提供数据的的聊天室
if(*it != clientfd){
if( send(*it, message, BUF_SIZE, 0) < 0 ) { perror("error"); exit(-1);}
}
}
}
return len;
}
#endif