网络socket的封装
network.h
#ifndef NETWORK_H
#define NETWORK_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
typedef struct NetWork
{
int type; //通信协议类型
int sock_fd; //socket描述符
struct sockaddr_in addr; //通信地址结构体
socklen_t addrlen;
bool is_svr; //是否是服务端
}NetWork;
typedef struct sockaddr* SP;
// 分配内存、创建socket、准备地址、绑定、监听、连接
NetWork* init_nw(int type,short port,const char* ip,bool is_svr);
//等待连接,只有type是SOCK_STREAM并且是服务端才能使用该函数
NetWork* accept_nw(NetWork* nw);
//具备send\sendto的发送函数
int send_nw(NetWork* nw,const void* buf,size_t len);
//具备recv\recvfrom的接收函数
int recv_nw(NetWork* nw,void* buf,size_t len);
//关闭socket、释放内存
void close_nw(NetWork* nw);
#endif//NETWORK_H
network.c
#include "network.h"
// 分配内存、创建socket、准备地址、绑定、监听、连接
NetWork* init_nw(int type,short port,const char* ip,bool is_svr)
{
NetWork* nw = malloc(sizeof(NetWork));
nw->type = type;
nw->sock_fd = socket(AF_INET,type,0);
if(0 > nw->sock_fd)
{
perror("socket");
free(nw);
return NULL;
}
nw->addr.sin_family = AF_INET;
nw->addr.sin_port = htons(port);
nw->addr.sin_addr.s_addr = inet_addr(ip);
nw->addrlen = sizeof(struct sockaddr_in);
nw->is_svr = is_svr;
if(is_svr)
{
if(bind(nw->sock_fd,(SP)&nw->addr,nw->addrlen))
{
perror("bind");
free(nw);
return NULL;
}
if(SOCK_STREAM == type && listen(nw->sock_fd,20))
{
perror("listen");
free(nw);
return NULL;
}
}
else if(SOCK_STREAM == type)
{
if(connect(nw->sock_fd,(SP)&nw->addr,nw->addrlen))
{
perror("connect");
free(nw);
return NULL;
}
}
return nw;
}
//等待连接,只有type是SOCK_STREAM并且是服务端才能使用该函数
NetWork* accept_nw(NetWork* nw)
{
if(SOCK_STREAM != nw->type || !nw->is_svr)
{
printf("只有TCP的服务端对象才能调用此函数\n");
}
//为新的NetWork分配内存
NetWork* cli_nw = malloc(sizeof(NetWork));
cli_nw->type = nw->type;
cli_nw->is_svr = true;
cli_nw->addrlen = nw->addrlen;
cli_nw->sock_fd = accept(nw->sock_fd,(SP)&cli_nw->addr,&cli_nw->addrlen);
if(0 >= cli_nw->sock_fd)
{
perror("accept");
free(cli_nw);
return NULL;
}
return cli_nw;
}
//具备send\sendto的发送函数
int send_nw(NetWork* nw,const void* buf,size_t len)
{
if(SOCK_STREAM == nw->type)
return send(nw->sock_fd,buf,len,0);
else
return sendto(nw->sock_fd,buf,len,0,(SP)&nw->addr,nw->addrlen);
}
//具备recv\recvfrom的接收函数
int recv_nw(NetWork* nw,void* buf,size_t len)
{
if(SOCK_STREAM == nw->type)
return recv(nw->sock_fd,buf,len,0);
else
return recvfrom(nw->sock_fd,buf,len,0,(SP)&nw->addr,&nw->addrlen);
}
//关闭socket、释放内存
void close_nw(NetWork* nw)
{
close(nw->sock_fd);
free(nw);
}
线程池的封装
由于线程池需要用到队列 我们先对 队列 进行封装
queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include <stdbool.h>
#include <stdio.h>
typedef struct Queue
{
void** arr;//内存首地址
size_t cal;//容量
int front;//队头
int back;//队尾
}Queue;
//创建队列
Queue* create_queue(size_t cal);
//销毁队列
void destory_queue(Queue* queue);
//队空
bool empty_queue(Queue* queue);
//队满
bool full_queue(Queue* queue);
//入队
void push_queue(Queue* queue,void* arg);
//出队
void pop_queue(Queue* queue);
//队头
void* front_queue(Queue* queue);
//队尾
void* back_queue(Queue* queue);
#endif//QUEUE_H
queue.c
#include <stdlib.h>
#include "queue.h"
//创建队列
Queue* create_queue(size_t cal)
{
Queue* queue = malloc(sizeof(Queue));
queue->arr = malloc(sizeof(void*)*(cal+1));
queue->cal = cal+1;
queue->front = 0;
queue->back = 0;
return queue;
}
//销毁队列
void destory_queue(Queue* queue)
{
free(queue->arr);
free(queue);
}
//队空
bool empty_queue(Queue* queue)
{
return queue->front == queue->back;
}
//队满
bool full_queue(Queue* queue)
{
return (queue->back+1)%queue->cal == queue->front;
}
//入队
void push_queue(Queue* queue,void* arg)
{
queue->arr[queue->back++] = arg;
queue->back %= queue->cal;
}
//出队
void pop_queue(Queue* queue)
{
queue->front = (queue->front+1)%queue->cal;
}
//队头
void* front_queue(Queue* queue)
{
return queue->arr[queue->front];
}
//队尾
void* back_queue(Queue* queue)
{
return queue->arr[(queue->back-1+queue->cal)%queue->cal];
}
threadpool.h
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include "queue.h"
#include <pthread.h>
typedef void (*WorkFP)(void*);//线程真正的业务逻辑函数格式
typedef struct Threadpool
{
int thread_cnt;//线程数量
pthread_t* tids;//线程ID的数组首地址
Queue* store_buf;//队列仓库
pthread_mutex_t flock;//队头互斥量
pthread_mutex_t block;//队尾互斥量
pthread_cond_t full;//满仓的条件变量
pthread_cond_t empty;//空仓的条件变量
WorkFP workfp;//线程的业务逻辑函数
}Threadpool;
//创建线程池
Threadpool* create_threadpool(int thread_cnt,int store_cal,WorkFP workfp);
//启动线程池
void start_threadpool(Threadpool* threadpool);
//生产数据
void push_threadpool(Threadpool* threadpool,void* data);
//消费数据
void* pop_threadpool(Threadpool* threadpool);
//销毁线程池
void destory_theadpool(Threadpool* threadpool);
#endif//THREADPOOL_H
threadpool.c
#include <stdlib.h>
#include "threadpool.h"
static void* run(void* arg)
{
Threadpool* threadpool = (Threadpool*)arg;
for(;;)
{
//消费数据
void* data = pop_threadpool(threadpool);
//如果能拿到数据,则执行业务逻辑函数
threadpool->workfp(data);
//本次任务结束,继续重新消费数据
}
}
//创建线程池
Threadpool* create_threadpool(int thread_cnt,int store_cal,WorkFP workfp)
{
//申请线程池内存
Threadpool* threadpool = malloc(sizeof(Threadpool));
threadpool->tids = malloc(sizeof(pthread_t)*thread_cnt);
threadpool->thread_cnt = thread_cnt;
threadpool->store_buf = create_queue(store_cal);
threadpool->workfp = workfp;
pthread_mutex_init(&threadpool->flock,NULL);
pthread_mutex_init(&threadpool->block,NULL);
pthread_cond_init(&threadpool->full,NULL);
pthread_cond_init(&threadpool->empty,NULL);
return threadpool;
}
//启动线程池
void start_threadpool(Threadpool* threadpool)
{
for(int i=0;i<threadpool->thread_cnt;i++)
{
pthread_create(threadpool->tids+i,NULL,run,threadpool);
}
}
//生产数据
void push_threadpool(Threadpool* threadpool,void* data)
{
//尝试对队尾加锁
pthread_mutex_lock(&threadpool->block);
while(full_queue(threadpool->store_buf))
{
//唤醒消费者线程
pthread_cond_signal(&threadpool->empty);
//休眠并解锁队尾
pthread_cond_wait(&threadpool->full,&threadpool->block);
}
//生产数据并存入队尾
push_queue(threadpool->store_buf,data);
//唤醒消费者线程
pthread_cond_signal(&threadpool->empty);
//解锁队尾
pthread_mutex_unlock(&threadpool->block);
}
//消费数据
void* pop_threadpool(Threadpool* threadpool)
{
pthread_mutex_lock(&threadpool->flock);
while(empty_queue(threadpool->store_buf))
{
pthread_cond_signal(&threadpool->full);
pthread_cond_wait(&threadpool->empty,&threadpool->flock);
}
void* data = front_queue(threadpool->store_buf);
pop_queue(threadpool->store_buf);
pthread_cond_signal(&threadpool->full);
pthread_mutex_unlock(&threadpool->flock);
return data;
}
//销毁线程池
void destory_theadpool(Threadpool* threadpool)
{
for(int i=0;i<threadpool->thread_cnt;i++)
{
pthread_cancel(threadpool->tids[i]);
}
pthread_mutex_destroy(&threadpool->flock);
pthread_mutex_destroy(&threadpool->block);
pthread_cond_destroy(&threadpool->full);
pthread_cond_destroy(&threadpool->empty);
destory_queue(threadpool->store_buf);
free(threadpool->tids);
free(threadpool);
}