**
常见服务器模型:
**
- 循环服务器
- 并发服务器
- 简单的并发服务器模型
- 使用线程池或进程池的服务器模型
- 使用I/O复用的并发服务器模块
UDP循环服务器模型
// UDP循环服务器模型
struct sockaddr_in local_addr,accept_addr;
// 填充local_addr,略
// 使用SOCK_DGRAM调用socket创建UDP套接字
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
bind(sockfd,(struct sockaddr *)&local_addr,sizeof(local_addr));
while(1){
recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&accept_addr,&len);
time_t now = time(NULL);
sprintf(buf,"%24s\n",ctime(&now));
sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&accept_addr,len);
}
TCP循环服务器模型
// TCP循环服务器模型
int sockfd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serv_addr,client_addr;
// 填充serv_addr
bind();
listen();
while(1){
int client_fd = accept(sockfd,(struct sockaddr*)&client_addr,&len);
// dosomething
close(client_fd);
}
close(sockfd);
简单的TCP并发服务器模型
// 简单的TCP并发服务器模型
int sockfd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serv_addr,client_addr;
// 填充serv_addr
bind();
listen();
while(1){
int client_fd = accept(sockfd,(struct sockaddr*)&client_addr,&len);
if(fork() == 0){
// dosomething for request
}
close(client_fd);
}
close(sockfd);
带线程池的TCP并发服务器模型
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
pthread_mutex_t alock = PTHREAD_MUTEX_INITITIALIZER;
static void *handle_request(void *argv){
int sockfd = *((int*)argv);
while(1){
pthread_mutex_lock(alock);
client_sock = accept();
pthread_mutex_unlock(alock);
// do something
}
}
static void handle_connect(int sockfd){
pthread_t thread_id[MAX_THREAD_NO];
int i;
for(i = 0;i < MAX_THREAD_NO;++i){
pthread_create(&thread_id[i],NULL,handle_request,(void *)&sockfd);
}
// 等待线程结束
for(i = 0;i < MAX_THREAD_NO;++i)
pthread_join(thread_id[i],NULL);
}
// 简单的TCP并发服务器模型
int main(){
int sockfd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serv_addr,client_addr;
// 填充serv_addr
bind();
listen();
handle_connect(sockfd);
close(sockfd);
return 0;
}
这里的线程池也可以换成进程,即在listen完成后创建N个进程,然后分别进行accept。而且使用进程不需要加锁,因为套接字描述符是共享的,linux内核会保证只有一个进程成功accept到客户端的请求。