注意epoll的性能提升,暂时我的理解比较浅
其实服务端的数据存储并不只限于mysql
可以是数组+mysql
可以是链表+mysql
可以是数组+链表+mysql
可以是线程池+mysql
可以是很多很多。。。。
用的是看个人能力,但如果基础不行,重构的几率就变的非常大
代码实现
内核链表
List.h
#include <stdlib.h>
#include <assert.h>
/*初始化链表list。链表为带头结点的双向循环链表*/
#define List_Init(list, list_node_t) { \
list=(list_node_t*)malloc(sizeof(list_node_t)); \
(list)->next=(list)->prev=list; \
}
//释放链表list中所有数据结点。list 为链表头指针,list_node_t为链表结点类型
#define List_Free(list, list_node_t) { \
assert(NULL!=list); \
list_node_t *tmpPtr; \
(list)->prev->next=NULL; \
while(NULL!=(tmpPtr=(list)->next)){ \
(list)->next=tmpPtr->next; \
free(tmpPtr); \
} \
(list)->next=(list)->prev=list; \
}
//销毁链表list,释放所有数据结点及头结点。 list为链表头指针,tmpPtr为链表结点临时指针变量
#define List_Destroy(list, list_node_t) { \
assert(NULL!=list); \
List_Free(list, list_node_t) \
free(list); \
(list)=NULL; \
}
//链表头插法,list为头指针,new为新节点
#define List_AddHead(list, newNode) { \
(newNode)->next=(list)->next; \
(list)->next->prev=newNode; \
(newNode)->prev=(list); \
(list)->next=newNode; \
}
//链表尾插法,list为头指针,new为新节点
#define List_AddTail(list, newNode) { \
(newNode)->prev=(list)->prev; \
(list)->prev->next=newNode; \
(newNode)->next=list; \
(list)->prev=newNode; \
}
//将新节点newNode加入到node之前
#define List_InsertBefore(node, newNode) { \
(newNode)->prev=(node)->prev; \
(newNode)->next=node; \
(newNode)->prev->next=newNode; \
(newNode)->next->prev=newNode; \
}
//将新节点newNode加入到node之后
#define List_InsertAfter(node, newNode) { \
(newNode)->next=node->next; \
(newNode)->prev=node; \
(newNode)->next->prev=newNode; \
(newNode)->prev->next=newNode; \
}
//判断链表是否为空,list为头指针
#define List_IsEmpty(list) ((list != NULL) \
&& ((list)->next == list) \
&& (list == (list)->prev))
//从删除链表结点node,
#define List_DelNode(node) {\
assert(NULL!=node && node!=(node)->next && node!=(node)->prev); \
(node)->prev->next=(node)->next; \
(node)->next->prev=(node)->prev; \
}
//从链表中删除并释放结点node
#define List_FreeNode(node) { \
List_DelNode(node); \
free(node); \
}
//使用指针curPos依次遍历链表list
#define List_ForEach(list, curPos) \
for ( curPos = (list)->next; \
curPos != list; \
curPos=curPos->next \
)
//分页数据结构体,简称分页器类型
typedef struct
{
int totalRecords; //总记录数
int offset; //当前页起始记录相对于第一条记录的偏移记录数
int pageSize; //页面大小
void *curPos; //当前页起始记录在链表中的结点地址
}Pagination_t;
//根据分页器paging的偏移量offset将分页器定位到链表list的对应位置
#define List_Paging(list, paging, list_node_t) { \
if(paging.offset+paging.pageSize>=paging.totalRecords){ \
Paging_Locate_LastPage(list, paging, list_node_t); }\
else { \
int i; \
list_node_t * pos=(list)->next; \
for( i=0; i<paging.offset && pos!=list ; i++) \
pos=pos->next; \
paging.curPos=(void*)pos; \
} \
}
//将分页器paging定位到链表list的第一页
#define Paging_Locate_FirstPage(list, paging) { \
paging.offset=0; \
paging.curPos=(void *)((list)->next); \
}
//将分页器paging定位到链表list的最后一页
#define Paging_Locate_LastPage(list, paging, list_node_t) { \
int i=paging.totalRecords % paging.pageSize; \
if (0==i && paging.totalRecords>0) \
i=paging.pageSize; \
paging.offset=paging.totalRecords-i; \
list_node_t * pos=(list)->prev; \
for(;i>1;i--) \
pos=pos->prev; \
paging.curPos=(void*)pos; \
\
}
//对于链表list及分页器paging,使用指针curPos依次遍历paging指向页面中每个结点
//这里i为整型计数器变量
#define Paging_ViewPage_ForEach(list, paging, list_node_t, pos, i) \
for (i=0, pos = (list_node_t *) (paging.curPos); \
pos != list && i < paging.pageSize; \
i++, pos=pos->next) \
//对于链表list,将分页器paging向前(后)移动offsetPage个页面.
//当offsetPage<0时,向前(链表头方向)移动|offsetPage|个页面
//当offsetPage>0时,向后(链末尾方向)移动offsetPage个页面
#define Paging_Locate_OffsetPage(list, paging, offsetPage, list_node_t) {\
int offset=offsetPage*paging.pageSize; \
list_node_t *pos=(list_node_t *)paging.curPos; \
int i; \
if(offset>0){ \
if( paging.offset + offset >= paging.totalRecords ) {\
Paging_Locate_LastPage(list, paging, list_node_t); \
}else { \
for(i=0; i<offset; i++ ) \
pos=pos->next; \
paging.offset += offset; \
paging.curPos= (void *)pos; \
} \
}else{ \
if( paging.offset + offset <= 0 ){ \
Paging_Locate_FirstPage(list, paging); \
}else { \
for(i=offset; i<0; i++ ) \
pos = pos->prev; \
paging.offset += offset; \
paging.curPos= pos; \
} \
} \
}
//根据分页器paging计算当前的页号
#define Pageing_CurPage(paging) (0==(paging).totalRecords?0:1+(paging).offset/(paging).pageSize)
//根据分页器paging计算的总的页数
#define Pageing_TotalPages(paging) (((paging).totalRecords%(paging).pageSize==0)?\
(paging).totalRecords/(paging).pageSize:\
(paging).totalRecords/(paging).pageSize+1)
//根据paging判断当前页面是否为第一页。结果为true表示是,否则false
#define Pageing_IsFirstPage(paging) (Pageing_CurPage(paging)<=1)
//根据paging判断当前页面是否为最后一页。结果为true表示是,否则false
#define Pageing_IsLastPage(paging) (Pageing_CurPage(paging)>=Pageing_TotalPages(paging))
改写的线程池
pthreadpool.h
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<pthread.h>
#include<assert.h>
typedef struct threadpool_task_t
{
//回调函数,任务运行时会调用此函数,也可声明成其它形式
void *(*process) (void *arg);
void *arg;/*回调函数的参数*/
struct threadpool_task_t *next;
}threadpool_task;
//线程池结构
typedef struct
{
pthread_mutex_t lock;
pthread_cond_t cond;
//链表结构,线程池中所有等待任务
threadpool_task *queue_head;
//是否销毁线程池
int shutdown;
pthread_t *threads;
//线程池中允许的活动线程数目
int max_thread_num;
//当前等待队列的任务数目
int queue_size;
}threadpool_t;
threadpool_t *pool;
int threadpool_add(void *(*process)(void *arg),void *arg);
int threadpool_destroy();
void *thread_routine(void *arg);
void pool_init(int max_thread_num);
void *myfunc(void* arg);
pthreadpool.c
#include "pthreadpool.h"
void pool_init(int max_thread_num)
{
pool=(threadpool_t *)malloc(sizeof(threadpool_t));
pthread_mutex_init(&(pool->lock),NULL);
pthread_cond_init(&(pool->cond),NULL);
pool->queue_head=NULL;
pool->max_thread_num=max_thread_num;
pool->queue_size=0;
pool->shutdown=0;
pool->threads=(pthread_t *)malloc(max_thread_num*sizeof(pthread_t));
int i=0;
for(i=0;i<max_thread_num;i++)
{
pthread_create(&(pool->threads[i]),NULL,thread_routine,NULL);
}
}
//向线程池中加入任务
int threadpool_add(void *(*process)(void *arg),void *arg)
{
//构造一个新任务
threadpool_task *newworker=(threadpool_task *)malloc(sizeof(threadpool_task));
newworker->process=process;
newworker->arg=arg;
//置为空
newworker->next=NULL;
pthread_mutex_lock(&(pool->lock));
//将任务加入到等待队列中
threadpool_task *member=pool->queue_head;
if(member!=NULL)
{
while(member->next!=NULL)
member=member->next;
member->next=newworker;
}
else
{
pool->queue_head=newworker;
}
assert(pool->queue_head!=NULL);
pool->queue_size++;
pthread_mutex_unlock (&(pool->lock));
/*等待队列中有任务了,唤醒一个等待线程;
如果所有线程都在忙碌,这句没有任何作用*/
pthread_cond_signal(&(pool->cond));
return 0;
}
/*销毁线程池,等待队列中的任务不会再被执行,正在运行的线程会一直
把任务运行完后再退出*/
int threadpool_destroy()
{
if(pool->shutdown)
return -1;//防止两次调用
pool->shutdown=1;
//唤醒所有等待线程,线程池要销毁了
pthread_cond_broadcast(&(pool->cond));
//阻塞等待线程退出,否则就成僵尸了
int i;
for(i=0;i<pool->max_thread_num;i++)
pthread_join(pool->threads[i],NULL);
free(pool->threads);
//销毁等待队列
threadpool_task *head=NULL;
while(pool->queue_head!=NULL)
{
head=pool->queue_head;
pool->queue_head=pool->queue_head->next;
free(head);
}
//条件变量和互斥量销毁
pthread_mutex_destroy(&(pool->lock));
pthread_cond_destroy(&(pool->cond));
free(pool);
//指针置空
pool=NULL;
return 0;
}
void *thread_routine(void *arg)
{
//printf("starting thread 0x%ld\n",pthread_self());
while (1)
{
pthread_mutex_lock(&(pool->lock));
/*如果等待队列为0并且不销毁线程池,则处于阻塞状态;
pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/
while (pool->queue_size==0&&!pool->shutdown)
{
//printf("thread 0x%ld is waiting\n",pthread_self());
pthread_cond_wait(&(pool->cond), &(pool->lock));
}
//线程池要销毁
if (pool->shutdown)
{
//遇到break,continue,return等跳转语句,不要忘记先解锁
pthread_mutex_unlock(&(pool->lock));
//printf ("thread 0x%ld will exit\n",pthread_self());
pthread_exit(NULL);
}
// printf("thread 0x%ld is starting to work\n",pthread_self());
assert(pool->queue_size!= 0);
assert(pool->queue_head!=NULL);
//等待队列长度减去1,并取出链表中的头元素
pool->queue_size--;
threadpool_task *worker=pool->queue_head;
pool->queue_head=worker->next;
pthread_mutex_unlock(&(pool->lock));
//调用回调函数,执行任务
(*(worker->process))(worker->arg);
free(worker);
worker=NULL;
}
//这一句是不可达的
pthread_exit(NULL);
}
/*
//测试
void *myfunc(void* arg)
{
printf("threadid is 0x%ld,working on task %d\n",pthread_self(),*(int *)arg);
//休息一秒,延长任务的执行时间
sleep(1);
return NULL;
}
int main(int argc,char **argv)
{
//static threadpool_t *pool;
//线程池中最多三个活动线程
pool_init (3);
//连续向池中投入10个任务
int *workingnum=(int *)malloc(sizeof(int)*10);
int i;
for(i=0;i<10;i++)
{
workingnum[i]=i;
threadpool_add(myfunc,&workingnum[i]);
}
//等待所有任务完成
sleep (5);
//销毁线程池
pool_destroy();
free(workingnum);
return 0;
}*/
wrang.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#include <pthread.h>
#include <netinet/in.h>
#include <poll.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <stddef.h>
#include <sys/un.h>
void sys_err(const char* s,int line);
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
int Bind(int fd, const struct sockaddr *sa, socklen_t salen);
int Connect(int fd, const struct sockaddr *sa, socklen_t salen);
int Listen(int fd, int backlog);
int Socket(int family, int type, int protocol);
ssize_t Read(int fd, void *ptr, size_t nbytes);
ssize_t Write(int fd, const void *ptr, size_t nbytes);
int Close(int fd);
ssize_t Readn(int fd, void *vptr, size_t n);
ssize_t Writen(int fd, const void *vptr, size_t n);
static ssize_t my_read(int fd, char *ptr);
ssize_t Readline(int fd, void *vptr, size_t maxlen);
void sys_err(const char* s,int line)
{
fprintf(stderr,"line:%d",line);
perror(s);
exit(1);
}
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
{
int n=0;
again:
if ((n=accept(fd,sa,salenptr))<0)
{
if ((errno==ECONNABORTED)||(errno==EINTR))
goto again;
else
sys_err("accept error",__LINE__);
}
return n;
}
int Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
int n=0;
if((n=bind(fd,sa,salen))<0)
sys_err("bind error",__LINE__);
return n;
}
int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{
int n=0;
if((n=connect(fd,sa,salen))<0)
sys_err("connect error",__LINE__);
return n;
}
int Listen(int fd, int backlog)
{
int n;
if((n=listen(fd,backlog))<0)
sys_err("listen error",__LINE__);
return n;
}
int Socket(int family, int type, int protocol)
{
int n;
if((n=socket(family,type,protocol))<0)
sys_err("socket error",__LINE__);
return n;
}
ssize_t Read(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
again:
if ((n=read(fd,ptr,nbytes))==-1)
{
if(errno==EINTR)
goto again;
else
return -1;
}
return n;
}
ssize_t Write(int fd, const void *ptr, size_t nbytes)
{
ssize_t n;
again:
if((n=write(fd,ptr,nbytes))==-1)
{
if(errno==EINTR)
goto again;
else
return -1;
}
return n;
}
int Close(int fd)
{
int n;
if((n=close(fd))==-1)
sys_err("close error",__LINE__);
return n;
}
/*参三: 应该读取的字节数*/
ssize_t Readn(int fd, void *vptr, size_t n)
{
size_t nleft; //usigned int 剩余未读取的字节数
ssize_t nread; //int 实际读到的字节数
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ((nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0;
else
return -1;
} else if (nread == 0)
break;
nleft -= nread;
ptr += nread;
}
return n - nleft;
}
ssize_t Writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0;
else
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}
static ssize_t my_read(int fd, char *ptr)
{
static int read_cnt;
static char *read_ptr;
static char read_buf[100];
if (read_cnt <= 0) {
again:
if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
if (errno == EINTR)
goto again;
return -1;
} else if (read_cnt == 0)
return 0;
read_ptr = read_buf;
}
read_cnt--;
*ptr = *read_ptr++;
return 1;
}
ssize_t Readline(int fd, void *vptr, size_t maxlen)
{
ssize_t n, rc;
char c, *ptr;
ptr = vptr;
for (n = 1; n < maxlen; n++) {
if ( (rc = my_read(fd, &c)) == 1) {
*ptr++ = c;
if (c == '\n')
break;
} else if (rc == 0) {
*ptr = 0;
return n - 1;
} else
return -1;
}
*ptr = 0;
return n;
}
server.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <time.h>
#include <pthread.h>
#include <mysql/mysql.h>
#include <sys/sendfile.h>
#include "wrang.h"
//#include "prest.h"
#include "List.h"
#include "pthreadpool.h"
//#define SERV_ADDRESS "47.94.14.45"
//#define SERV_ADDRESS "127.0.0.1"
#define SERV_ADDRESS "192.168.30.185"
//#define SERV_ADDRESS "192.168.1.184"
#define SERV_PORT 8013
#define MAX 50
#define MAX_CHAR 300
#define SAVE 10
#define REGISTER 1
#define LOGIN 2
#define MODIFY 3
#define ADD_FRIEND 4
#define DEL_FRIEND 5
//#define QUERY_FRIEND 6
#define PRIVATE_CHAT 7
#define VIEW_FRIEND_LIST 8
//#define SHOW_FRIEND_STATUS 9
#define VIEW_CHAT_HISTORY 10
#define SHIELD 11
#define UNSHIELD 12
#define SHOW_FRIEND 13
//#define GET_FRIEND_STATUS 14
#define CREAT_GROUP 15
#define ADD_GROUP 16
#define DEL_GROUP 17
#define WITHDRAW_GROUP 18
#define KICK 19
#define SET_GROUP_ADMIN 20
#define VIEW_ADD_GROUP 21
#define VIEW_GROUP_MEMBER 22
#define VIEW_GROUP_RECORD 23
#define SEND_FILE 24
#define GROUP_CHAT 25
#define ADD_FRIEND_APPLY 26
#define DEL_FRIEND_APPLY 27
#define PRIVATE_CHAT_APPLY 28
#define SHIELD_APPLY 29
#define UNSHIELD_APPLY 30
#define VIEW_FRIEND_LIST_APPLY 31
//#define SHOW_FRIEND_STATUS_APPLY 32
#define CREAT_GROUP_APPLY 33
#define ADD_GROUP_APPLY 34
#define DEL_GROUP_APPLY 35
#define WITHDRAW_GROUP_APPLY 36
#define SET_GROUP_ADMIN_APPLY 37
#define KICK_APPLY 38
#define VIEW_ADD_GROUP_APPLY 39
#define VIEW_GROUP_MEMBER_APPLY 40
#define MESSAGE_RECORD 41
#define REGISTER_APPLY 42
#define LOGIN_APPLY 43
#define PRINT_APPLY 44
#define ADD_FRIEND_ACCEPT 45
#define VIEW_CHAT_HISTORY_APPLY 46
#define ADD_FRIEND_ACCEPT_APPLY 47
#define GROUP_APPLY 48
#define ADD_GROUP_ACCEPT 49
#define ADD_GROUP_ACCEPT_APPLY 50
#define VIEW_GROUP_RECORD_APPLY 51
#define GROUP_CHAT_APPLY 52
#define RECV_FILE 53
//#define REGISTER_ERROR_APPLY 54
#define EXIT 54
//#define EXIT_APPLY 55
#define RECV_APPLY 55
#define UPLOAD 56
#define DOWNLOAD 57
#define DOWNLINE 0
#define ONLINE 1
#define OWNER 1
#define ADMIN 2
#define COMMON 3
#define ADOPTER 4
#define STRANGER 0
#define PAL 1
#define BLACK 2
#define UNBLACK 3
#define MAX_THREAD_NUM 10
typedef struct message
{
int flag;
int id;
char message[256];
}message;
typedef struct apply_messgae
{
int flag;
int sender;
int recver;
int send_fd;
int recv_fd;
char message[256];
}apply_messgae;
typedef struct chat_message
{
int flag;
int sender;
int recver;
char message[256];
//char time[30];
}Chat_message;
typedef struct box
{
int flag;
int sender;
int recver;
int send_fd;
int recv_fd;
char message[256];
}box_t;
typedef struct relation_info
{
int flag;
int send;
int recv;
int relation;
char message[256];
}Relation_t;
typedef struct friend_info
{
int flag;
int send;
int recv;
int status;
int relation;
char name[MAX];
char message[256];
}Friend_t;
typedef struct group_info
{
int flag;
int group_owner;
int admin;
char group_name[MAX];
}Group_t;
typedef struct group_leader
{
int flag;
int sender;
int recver;
int admin;
char message[256];
}Group_leader;
//服务器保存用户信息结构体
typedef struct account
{
int flag;
int id;
char name[MAX];
char password[MAX];
struct sockaddr_in useraddr;
int online; //1:开;0:关
int connfd; //链接套接字
}Account_t;
int user_num;
typedef struct server_user
{
int connfd;
int id;
char name[MAX];
char password[MAX];
}server_user_t;
typedef struct server_user_node
{
server_user_t data;
struct server_user_node* next;
struct server_user_node* prev;
}server_user_node_t,*server_list_t;
server_list_t list_ser;
typedef struct file
{
int flag;
int sender;
int recver;
int file_size;
char file_name[100];
char data[800];
}file_t;
int lfd;
int epfd;
int cfd;
void Init_socket();
void *Recv_pack(void* arg);
void Turn_worker_thread();
void *work(void* arg);
void Login(int fd,char* buf);
void Send_offline_apply(int fd,int recver);
void Send_offline_messgae(int fd,int recver);
void Register(int fd,char* buf);
void Exit(int fd,char* buf);
void Add_friend(int fd,char* buf);
void Add_friend_accept(int fd,char* buf);
void Del_friend(int fd,char* buf);
void Shield_friend(int fd,char* buf);
void Unshield_friend(int fd,char* buf);
//一起实现
//void Show_friend_status();
void View_friend_list(int fd,char* buf);
int Check_relationship(int fd,int send,int recv);
void Private_chat(int fd,char* buf);
void View_chat_history(int fd,char* buf);
void Create_group(int fd,char* buf);
void Add_group(int fd,char* buf);
void Add_group_accept(int fd,char* buf);
void Withdraw_group(int fd,char* buf);
//一起实现
void View_group_member(int fd,char* buf);
void View_add_group(int fd,char* buf);
void Group_chat(int fd,char* buf);
void View_group_record(int fd,char* buf);
void Set_group_admin(int fd,char* buf);
void Kick(int fd,char* buf);
int Check_relationship2(int fd,int send,int recv);
void Upload(int fd,char* buf);
void *Send_file(void *arg);
void Recv_file(int fd,char* buf);
void Download(int fd,char* buf);
void my_err(const char* err_string,int line);
void Connect_mysql();
void Close_mysql(MYSQL mysql);
int Get_connfd(int id);
void Send_pack(int fd,int flag,char* buf);
void Send_connfd_pack(int flag,int sender,int recver,char* buf);
void Send_pack_name(int flag ,int sender,int recver,char *buf);
void Mysql_with_error(MYSQL* mysql);
void Signal_close(int i);
void Add_node(int fd,int id,char* name);
void Send_register_pack(int fd,int flag,char* buf,int id);
int Get_status(int id);
char* Get_name(int id);
server.c
#include "server.h"
#define EPOLLEVENT 1024
#define BUFMAX 1024
#define BUF 2048
char *Server_time();
int Set_no_block(int sfd);
int sys_log;
MYSQL mysql;
/*
void Add_node(int fd,int id,char* name);
void Send_register_pack(int fd,int flag,char* buf,int id);
int Get_status(int id);
char* Get_name(int id);*/
int main()
{
/*if((sys_log=open("sys_log",O_WRONLY | O_CREAT | O_APPEND,S_IRUSR|S_IWUSR))<0)
{
sys_err("open error",__LINE__);
return 0;
}
dup2(sys_log,1);*/
signal(SIGINT,Signal_close);
//pthread_mutex_init(&mutex,NULL);
//pthread_cond_init(&cond,NULL);
Connect_mysql();
/*printf("线程池启动\n");
pool_init(MAX_THREAD_NUM);
printf("线程池启动成功!\n");
sleep(2);*/
pool_init(50);
//sleep(2);
//Read_from_mysql();
Init_socket();
//threadpool_destroy();
}
void Signal_close(int i)
{
close(sys_log);
Close_mysql(mysql);
printf("服务器关闭\n");
exit(1);
}
char *Server_time()
{
time_t ctime;//服务器时间
struct tm *server_time;
time(&ctime);
server_time=localtime(&ctime);
return asctime(server_time);
}
int Set_no_block(int sfd)
{
/* 内层调用fcntl()的F_GETFL获取flag,
* 外层fcntl()将获取到的flag设置为O_NONBLOCK非阻塞*/
if( fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL, 0) ) == -1)
{
return -1;
}
return 0;
}
void Init_socket(int argc,char *argv[])
{
struct stat stat_buf;
const char* file_name=argv[1];
int file_fd=open(file_name,O_RDONLY);
fstat(file_fd,&stat_buf);
close(file_fd);
List_Init(list_ser,server_user_node_t);
printf("服务端启动\n");
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socklen_t cli_addr_len;
lfd=Socket(AF_INET,SOCK_STREAM,0);
Set_no_block(lfd);
//端口复用
int opt=1;
setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));
bzero(&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERV_PORT);
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
Bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
Listen(lfd,128);
printf("服务器启动成功!\n");
epfd=epoll_create(EPOLLEVENT);
struct epoll_event tep,ep[EPOLLEVENT];
tep.events=EPOLLIN;
tep.data.fd=lfd;
epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&tep);
int i;
int ret;
pthread_t pid;
char buf[BUFMAX];
//memset(buf,0,sizeof(buf));
while(1)
{
ret=epoll_wait(epfd,ep,EPOLLEVENT,-1);
for(i=0;i<ret;i++)
{
//printf("the event is %x\n",ep[i].events);
int fd=ep[i].data.fd;
if (!(ep[i].events & EPOLLIN)) //如果不是"读"事件, 继续循环
continue;
if(ep[i].data.fd==lfd)
{
cli_addr_len=sizeof(cli_addr);
cfd=Accept(lfd,(struct sockaddr*)&cli_addr,&cli_addr_len);
printf("连接到新的客户端ip:%s\n端口号:%d\n",inet_ntoa(cli_addr.sin_addr),cli_addr.sin_port);
/*设置非阻塞io*/
if(Set_no_block(cfd) != 0 )
{
printf("SET_no_black\n");
printf("%s",Server_time());
close(cfd);
continue;
}
tep.events=EPOLLIN;
tep.data.fd=cfd;
if(epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&tep)<0)
{
printf("EPOLL_CTL add client error\n");
printf("%s",Server_time());
close(cfd);
continue;
}
}
/*else if(ep[i].events & EPOLLOUT)
{
printf("start to sendfile !\n");
printf("处理写事件\n");
int write;
write=send(fd,buf,strlen(buf),0);
if(write == -1)
{
my_err("write event error",__LINE__);
close(fd);
}
else
{