**
常見服務器模型:
**
- 循環服務器
- 併發服務器
- 簡單的併發服務器模型
- 使用線程池或進程池的服務器模型
- 使用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到客戶端的請求。