Unix網絡編程——常見服務器模型

**

常見服務器模型:

**
- 循環服務器
- 併發服務器

  • 簡單的併發服務器模型
  • 使用線程池或進程池的服務器模型
  • 使用I/O複用的併發服務器模塊

UDP循環服務器模型

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循環服務器模型

// 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併發服務器模型

// 簡單的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到客戶端的請求。

I/O複用循環式TCP服務器模型

見Unix網絡編程—— I/O複用之select

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章