几种并发服务器模型的实现



客户端使用select模型:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <errno.h>
  5 #include <sys/types.h>
  6 #include <sys/socket.h>
  7 #include <netinet/in.h>
  8 #include <arpa/inet.h>
  9 #include <sys/select.h>
 10 #include <signal.h>
 11
 12 #define ERR_EXIT(m)  13     do {  14         perror(m); 15         exit(EXIT_FAILURE); 16     }while(0)
 17
 18 static void do_client(int fd)
 19 {
 20     char recvbuf[MAXLINE + 1] = {0};
 21     char sendbuf[MAXLINE + 1] = {0};
 22
 23     fd_set reade, ready;
 24     FD_ZERO(&reade);
 25     int fd_stdin = fileno(stdin);
 26     FD_SET(fd_stdin, &reade);
 27     FD_SET(fd, &reade);
 28     int fd_max = (fd_stdin > fd) ? fd_stdin : fd;
 29
 30     int ret;
 31     while(1)
 32     {
 33         ready = reade;
 34         ret = select( fd_max+1, &ready, NULL, NULL, NULL);//轮询
 35         if(ret == -1)
 36         {
 37             if(errno == EINTR)
 38                 continue;
 39             ERR_EXIT("select");
 40         }else if(ret ==  0)
 41         {
 42             continue;
 43         }
 44
 45         if(FD_ISSET(fd_stdin, &ready))
 46         {
 47             if(fgets(sendbuf, sizeof(sendbuf), stdin) == NULL)
 48             {
 49                 close(fd);
 50                break;
 51             }else
 52             {
 53                 if( -1 == write(fd, sendbuf, strlen(sendbuf)))
 54                     printf("write\n");
 55             }
 56         }
 57
 58
 59         if(FD_ISSET(fd, &ready))
 60         {
 61             int nread = read(fd, recvbuf, MAXLINE);
 62             if(nread < 0)
 63                 ERR_EXIT("read");
 64             if(nread == 0)//如果没接收到消息,打印关闭描述符,退出循环
 65             {
 66                 fprintf(stdout, "fd close\n");
 67                 break;
 68             }
 69             fprintf(stdout, "receive:%s", recvbuf);
 70         }
 71         memset(recvbuf, 0, sizeof recvbuf);
 72         memset(sendbuf, 0, sizeof sendbuf);
 73     }
 74 }
 75 void handle(int signum)
 76 {
 77 printf("sigpipe\n");
 78 }
 79
 80 int main(int argc, const char *argv[])
 81 {
 82     signal(SIGPIPE, SIG_IGN);
 83     int fd = socket(AF_INET, SOCK_STREAM, 0);
 84     if(fd < 0)
 85         ERR_EXIT("socket");
 86
 87     struct sockaddr_in cliaddr;
 88     cliaddr.sin_family = AF_INET;
 89     cliaddr.sin_port = htons(8888);
 90     cliaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
 91     socklen_t len = sizeof cliaddr;
 92
 93     int ret ;
 94     if((ret = connect(fd, (struct sockaddr*)&cliaddr, len)) == -1)
 95     {
 96         close(fd);
 97         ERR_EXIT("connect");
 98     }
 99     do_client(fd);
100     close(fd);
101     return 0;
102 }

1.并发多进程服务器

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <errno.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include "rio.h"//封装了网络编程中的readn  writen   readline 3个函数

#include <signal.h>

#define ERR_EXIT(m) \

    do
{ \

        perror(m);\

        exit(EXIT_FAILURE);\

    }while(0)

static
void do_service(int
fd)

{

    rio_t rt;

    rio_init(&rt, fd);

    char
recvbuf[1024] = {0};

    int
ret;

    while(1)

    {

        memset(recvbuf, 0,
sizeof recvbuf);

        ret = rio_readline(&rt, recvbuf, 1024);

        if(ret == 0)  

        {

            close(fd);

            exit(EXIT_SUCCESS);

        }

        rio_writen(fd, recvbuf,
strlen(recvbuf)) ;

    }

}

void
handle(int
signum)
//对SIGCHLD信号的处理函数

{

    while(waitpid(-1, NULL, WNOHANG) > 0);

    return
;

}

int
listenf();
//封装了socket,bind,listen3个函数,返回需要监听的连接socket描述符

int
main(
int argc,
const
char
*argv[])

{

    if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)//对客户端关闭导致的信号的处理

        ERR_EXIT("signal_pipe");

    if(signal(SIGCHLD, handle) == SIG_ERR)//对子进程结束后资源的回收

        ERR_EXIT("signal_chld");

    int
listenfd = listenf();

    struct
sockaddr_in cliaddr;

    bzero(&cliaddr,
sizeof(cliaddr));

    socklen_t cli_len =
sizeof cliaddr;

    int
clientfd;

    while(1)

    {

        clientfd = accept(listenfd, (struct
sockaddr*)&cliaddr, &cli_len);

        if(clientfd == -1) 

        {

            close(listenfd);

            ERR_EXIT("accept");

        }

        

        int
pid;

        if((pid = fork()) == -1)

        {

            ERR_EXIT("fork");

        }else
if(pid == 0)

        {

            close(listenfd);

            do_service(clientfd);

            exit(EXIT_SUCCESS);

        }

        close(clientfd);

    }

    close(listenfd);

    return
0;

}

int
listenf()

{

    int
listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd

    if(listenfd == -1 )

        ERR_EXIT("socket");

    int
on = 1;

    if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) == -1)//setsockopt设置端口复用

    {

        close(listenfd);

        ERR_EXIT("setsockopt");

    }

    struct
sockaddr_in seraddr;

    seraddr.sin_family = AF_INET;

    seraddr.sin_port = htons(8888);

    seraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    socklen_t len =
sizeof(seraddr);

    if(bind(listenfd, (struct
sockaddr*)&seraddr, len) == -1)//监听socket端口,

    {

        close(listenfd);

        ERR_EXIT("bind");

    }

    if(listen(listenfd, 6) == -1)

    {

        close(listenfd);

        ERR_EXIT("listen");

    }

    return
listenfd;

}

2.多线程服务器模型:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <errno.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include "rio.h"

#include <signal.h>

#include <pthread.h>

#define ERR_EXIT(m) \

    do
{ \

        perror(m);\

        exit(EXIT_FAILURE);\

    }while(0)

static
void do_service(int
fd)

{

    rio_t rt;

    rio_init(&rt, fd);

    char
recvbuf[1024] = {0};

    int
ret;

    int
rcnt = 0;

    while(1)

    {

        memset(recvbuf, 0,
sizeof recvbuf);

        ret = rio_readline(&rt, recvbuf, 1024);

         if(ret == 0)

         {

         close(fd);

//         break;

          pthread_exit(NULL);

         }

         write(fd, recvbuf,
strlen(recvbuf)) ;

    }

}

void
handle(int
signum)

{

    printf("hello\n");

}

void
*pthread_func(void
*arg)

{

    pthread_detach(pthread_self());

    int
*q = (int*)arg;

   int
p = *(int*)arg;

   free(q);

     do_service(p);

     close(p);

}

int
listenf();

int
main(
int argc,
const
char
*argv[])

{

    if(signal(SIGPIPE, handle) == SIG_ERR)

        ERR_EXIT("signal");

    int
listenfd = listenf();

    struct
sockaddr_in cliaddr;

    bzero(&cliaddr,
sizeof(cliaddr));

    socklen_t cli_len =
sizeof cliaddr;

    int
clientfd;

    while(1)

    {

    clientfd = accept(listenfd, (struct
sockaddr*)&cliaddr, &cli_len);

    if(clientfd == -1) 

    {

        close(listenfd);

        ERR_EXIT("accept");

    }

    pthread_t tid;

    int
*p = (int*)malloc(sizeof(int));

   *p = clientfd;

    pthread_create(&tid, NULL, pthread_func, p);

    }

    close(listenfd);

    return
0;

}

int
listenf()

{

    int
listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd

    if(listenfd == -1 )

        ERR_EXIT("listen");

    int
on = 1;

    if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) == -1)//setsockopt设置端口复用

    {

        close(listenfd);

        ERR_EXIT("setsockopt");

    }

    struct
sockaddr_in seraddr;

    seraddr.sin_family = AF_INET;

    seraddr.sin_port = htons(8888);

    seraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    socklen_t len =
sizeof(seraddr);

    if(bind(listenfd, (struct
sockaddr*)&seraddr, len) == -1)//监听socket端口,

    {

        close(listenfd);

        ERR_EXIT("bind");

    }

    if(listen(listenfd, 6) == -1)

    {

        close(listenfd);

        ERR_EXIT("listen");

    }

return
listenfd;

}

3.select服务器模型:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <sys/types.h>
  7 #include <sys/stat.h>
  8 #include <sys/socket.h>
  9 #include <arpa/inet.h>
 10 #include <signal.h>
 11 #include <sys/select.h>
 12 #define MAXLEN 1024
 13
 14 #define ERR_EXIT(m)  15     do {  16         perror(m); 17         exit(EXIT_FAILURE); 18     }while(0)
 19
 20 int listenf();//封装了网络socket的socekt,bind,listen函数,返回监听的socket描述符
 21 void handle(int signum)//SIGPIPE(子进程结束)的信号的处理
 22 {
 23     printf("hello\n");
 24 }
 25 static void do_select(int);
 26
 27 int main(int argc, const char *argv[])
 28 {
 29     if(signal(SIGPIPE, handle) == SIG_ERR)
 30         ERR_EXIT("signal");
 31     int listenfd = listenf();
 32     do_select(listenfd);
 33     close(listenfd);
 34     return 0;
 35 }
 36
 37 int listenf()
 38 {
 39     int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd
 40     if(listenfd == -1 )
 41         ERR_EXIT("listen");
 42
 43     int on = 1;
 44     if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用
 45     {
 46         close(listenfd);
 47         ERR_EXIT("setsockopt");
 48     }
 49
 50     struct sockaddr_in seraddr;
 51     seraddr.sin_family = AF_INET;
 52     seraddr.sin_port = htons(8888);
 53     seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 54     socklen_t len = sizeof(seraddr);
 55     if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口,
 56     {
 57         close(listenfd);
 58         ERR_EXIT("bind");
 59     }
 60
 61     if(listen(listenfd, 6) == -1)
 62     {
 63         close(listenfd);
 64         ERR_EXIT("listen");
 65     }
 66     return listenfd;
 67 }
 68
 69 void do_select(int fd)
 70 {
 71     //struct sockaddr_in cliaddr;
 72     //memset(&cliaddr, 0, sizeof(cliaddr));//此处不需要客户端的地址信息
 73     fd_set set;
 74     fd_set rset;
 75     FD_ZERO(&rset);
 76     FD_SET(fd, &rset);
 77     int nready;
 78     int fd_set[MAXLEN];
 79
 80     int i;
 81     for(i = 0;i < MAXLEN; ++i)
 82         fd_set[i] = -1;
 83     fd_set[0] = fd;
 84
 85     int maxi = fd;//初始最大轮询fd是监听的fd
 86     int  arrlen = 1;//表示数组长度
 87
 88    char recvbuf[1024] = {0};
 89     while(1)
 90     {
 91         set = rset;
 92         nready = select(maxi+1, &set, NULL, NULL, NULL);
 93         if(nready == -1)
 94         {
 95             ERR_EXIT("select");
 96         }
 97         if(FD_ISSET(fd, &set))//查看书否有新的客户端请求
 98         {
 99             int clifd = accept(fd, NULL, NULL);
100             if(clifd == -1)
101                 ERR_EXIT("accept");
102             for(i = 1; i < MAXLEN; ++i)
103             { if(fd_set[i] == -1)
104                 {
105                     fd_set[i] = clifd;
106                     break;
107                 }
108             }
109             FD_SET(clifd, &rset);
110             if(clifd > maxi)
111                 maxi = clifd;
112             arrlen++;
113             --nready;
114         }
115
116         for(i = 1; i < arrlen; ++i)//轮询数据连接
117         {
118             int set_fd = fd_set[i];
119          if(FD_ISSET(set_fd, &set))
120          {
121             int n = read(set_fd, recvbuf, 1024);
122             if(n == -1)
123                 ERR_EXIT("read");
124             else if(n == 0)//客户端退出,
125             {
126               FD_CLR(set_fd, &rset);
127               close(set_fd);
128               fd_set[i] = -1;
129               arrlen--;
130             }
131             write(set_fd, recvbuf, strlen(recvbuf));
132                memset(recvbuf, 0, 1024);
133          if(--nready < 0)
134              break;
135          }
136         }
137     }
138 }

4

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <sys/types.h>
  7 #include <sys/stat.h>
  8 #include <sys/socket.h>
  9 #include <arpa/inet.h>
 10 #include <signal.h>
 11 #include <poll.h>
 12 #define MAXLEN 1024
 13
 14 #define ERR_EXIT(m)  15     do {  16         perror(m); 17         exit(EXIT_FAILURE); 18     }while(0)
 19
 20 static void do_service(int);
 21 int listenf();
 22 void handle(int signum)
 23 {
 24     printf("hello\n");
 25 }
 26 static void do_poll(int);
 27
 28 int main(int argc, const char *argv[])
 29 {
 30     if(signal(SIGPIPE, handle) == SIG_ERR)
 31         ERR_EXIT("signal");
 32     int listenfd = listenf();
 33     do_poll(listenfd);
 34     close(listenfd);
 35     return 0;
 36 }
 37
 38 int listenf()
 39 {
 40     int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd
 41     if(listenfd == -1 )
 42         ERR_EXIT("listen");
 43
 44     int on = 1;
 45     if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用
 46     {
 47         close(listenfd);
 48         ERR_EXIT("setsockopt");
 49     }
 50
 51     struct sockaddr_in seraddr;
 52     seraddr.sin_family = AF_INET;
 53     seraddr.sin_port = htons(8888);
 54     seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 55     socklen_t len = sizeof(seraddr);
 56     if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口,
 57     {
 58         close(listenfd);
 59         ERR_EXIT("bind");
 60     }
 61
 62     if(listen(listenfd, 6) == -1)
 63     {
 64         close(listenfd);
 65         ERR_EXIT("listen");
 66     }
 67     return listenfd;
 68 }
 69
 70 void do_poll(int fd)
 71 {
 72     struct pollfd pfd[MAXLEN];//设置的最大连接数,存放结构体信息
 73     char recvbuf[1024] = {0};
 74     int i;
 75     for(i = 0; i < MAXLEN; ++i)
 76         pfd[i].fd = -1;
 77
 78     pfd[0].fd = fd;
 79     pfd[0].events = POLLIN;//将监听连接的描述符防止数组开头
 80
 81     int nready;
 82     int maxi = 0;
 83     while(1)
 84     {
 85         nready = poll(pfd, maxi+1, -1);//轮询的是有效数组长度,不能少1
 86         if(nready == -1)
 87         {
 88             ERR_EXIT("select");
 89         }
 90
 91         if(pfd[0].revents & POLLIN)//有客户端请求连接
 92         {
 93             int clifd = accept(fd, NULL, NULL);
 94             if(clifd == -1)
 95                 ERR_EXIT("accept");
 96             for(i = 1; i < MAXLEN; ++i)
 97             {
 98                 if(pfd[i].fd == -1)
 99                 {
100                     pfd[i].fd = clifd;
101                     pfd[i].events = POLLIN;
102                     break;
103                 }
104             }
105             if(i > maxi)
106                 maxi = i;
107             --nready;
108         }
109
110         for(i = 1; i <= maxi; ++i)
111         {
112             if(pfd[i].fd == -1)
113                 continue;
114
115             if( pfd[i].revents & POLLIN)
116             {
117                 int n = read(pfd[i].fd, recvbuf, 1024);
118                 if(n == -1)
119                     ERR_EXIT("read");
120                 else if(n == 0)//客户端退出,则从集合中清除
121                 {
122                     printf("%d close\n", pfd[i].fd);
123                     close(pfd[i].fd);
124                     pfd[i].fd = -1;
125                     continue;
126                 }
127                 write(pfd[i].fd, recvbuf, strlen(recvbuf));
128                 memset(recvbuf, 0, 1024);
129
130                 if(--nready < 0)
131                     break;
132             }
133         }
134     }
135 }

5.epoll服务器模型:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <sys/types.h>
  7 #include <sys/stat.h>
  8 #include <sys/socket.h>
  9 #include <arpa/inet.h>
 10 #include <signal.h>
 11 #include <sys/epoll.h>
 12 #define MAXLEN 1024
 13
 14 #define ERR_EXIT(m)  15     do {  16         perror(m); 17         exit(EXIT_FAILURE); 18     }while(0)
 19
 20 int listenf();
 21 static void do_epoll(int);
 22
 23 int main(int argc, const char *argv[])
 24 {
 25     int listenfd = listenf();
 26     do_epoll(listenfd);
 27     close(listenfd);
 28     return 0;
 29 }
 30
 31 int listenf()
 32 {
 33     int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd
 34     if(listenfd == -1 )
 35         ERR_EXIT("listen");
 36
 37     int on = 1;
 38     if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用
 39     {
 40         close(listenfd);
 41         ERR_EXIT("setsockopt");
 42     }
 43
 44     struct sockaddr_in seraddr;
 45     seraddr.sin_family = AF_INET;
 46     seraddr.sin_port = htons(8888);
 47     seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 48     socklen_t len = sizeof(seraddr);
 49     if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口,
 50     {
 51         close(listenfd);
 52         ERR_EXIT("bind");
 53     }
 54
 55     if(listen(listenfd, 6) == -1)
 56     {
 57         close(listenfd);
 58         ERR_EXIT("listen");
 59     }
 60     return listenfd;
 61 }
 62
 63 void do_epoll(int fd)
 64 {
 65     char recvbuf[MAXLEN] = {0};
 66     int epollfd = epoll_create(2048);//设置的最大连接数
 67     if(epollfd == -1)
 68         ERR_EXIT("epoll_create");
 69
 70     struct epoll_event ev;
 71     ev.data.fd = fd;
 72     ev.events = EPOLLIN;
 73     if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1)//加入轮询
 74                  ERR_EXIT("epoll_ctl_add");
 75
 76     struct epoll_event events[2048];//数组在epoll_wait返回结果的时候使用
 77     int ret;
 78     int i;//在下面while的for循环中遍历使用
 79     int rfd;
 80     int clientfd;
 81     int nread;
 82     while(1)
 83     {
 84         ret = epoll_wait(epollfd, events, 2048, -1);
 85         if(ret == -1)
 86             ERR_EXIT("epoll_wait");
 87
 88         for(i = 0; i < ret; ++i )
 89         {
 90             rfd = events[i].data.fd;
 91             if(rfd == fd)
 92             {
 93                 if((clientfd = accept(fd, NULL, NULL)) == -1)
 94                 ERR_EXIT("accept");
 95                 ev.data.fd = clientfd;
 96                 ev.events = EPOLLIN;
 97                 if(epoll_ctl(epollfd, EPOLL_CTL_ADD, clientfd, &ev) == -1)
 98                     ERR_EXIT("epoll_ctl");
 99             }else
100             {
101                 int nread = read(rfd, recvbuf, MAXLEN);
102                 if(nread == -1)
103                 {
104                     if(errno == EINTR)
105                         continue;
106                     ERR_EXIT("read");
107                 }else if( nread == 0)//客户端退出,从epoll轮询中删除
108                 {
109                     printf("%d fd close\n", rfd);
110                     ev.data.fd = rfd;
111                     ev.events = EPOLLIN;
112                     if(epoll_ctl(epollfd, EPOLL_CTL_DEL, rfd, &ev) == -1)
113                         ERR_EXIT("epoll_ctl");
114                 }else
115                 {
116                     if(write(rfd, recvbuf, strlen(recvbuf)) == -1)
117                         ERR_EXIT("write");
118                     memset(recvbuf, 0, MAXLEN);
119                 }
120             }
121         }
122     }
123     close(epollfd);
124 }

时间: 2024-11-05 12:24:49

几种并发服务器模型的实现的相关文章

几种并发服务器模型的实现:多线程,多进程,select,poll,epoll

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <arpa/inet.h> #include &q

Linux下几种并发服务器的实现模式

Linux下的几种并发服务器的设计模式 1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循环服务器:一个server只能一次只能接收一个client,当当前client结束访问之后才能进行下一个client的连接. 2.并发服务器:一个server同一时间可以响应很多客户端的访问. 3>select+多线程模式 并发服务器的三种实现方式 1.多进程并发

IO复用、多进程和多线程三种并发编程模型

I/O复用模型 I/O复用原理:让应用程序可以同时对多个I/O端口进行监控以判断其上的操作是否可以进行,达到时间复用的目的.在书上看到一个例子来解释I/O的原理,我觉得很形象,如果用监控来自10根不同地方的水管(I/O端口)是否有水流到达(即是否可读),那么需要10个人(即10个线程或10处代码)来做这件事.如果利用某种技术(比如摄像头)把这10根水管的状态情况统一传达到某一点,那么就只需要1个人在那个点进行监控就行了,而类似与select或epoll这样的多路I/O复用机制就好比是摄像头的功能

码海拾遗:高并发服务器模型简述

常见的Linux并发服务器模型有:多进程并发服务器.多线程并发服务器.select多路I/O转接模型.poll多路I/O转接模型.epoll多路I/O转接模型. 1.多进程并发服务器.多线程并发服务器 多进程并发服务器考虑因素: 父进程最大文件描述符个数(父进程中需要close关闭accept返回的新文件描述符) 系统内存创建进程个数(与内存大小相关) 进程创建过多是否降低整体服务性能(进程调度) 多线程并发服务器考虑因素: 调用进程内最大文件描述符上限 如果线程中需要共享数据,则需要考虑线程同

go---&gt;共享内存和通信两种并发模式原理探究

共享内存和通信两种并发模式原理探究 并发理解 人类发明计算机编程的本质目的是为了什么呢?毫无疑问是为了解决人类社会中的各种负责业务场景问题.ok,有了这个出发点,那么想象一下,比如你既可以一心一意只做一件事,你也可以同时做多件事,比如,你计划今天上午计划就是看足球比赛,ok,你今天的工作就是串行的,单进程的,你只需要完成一件事.但是不巧呢,你妈妈说让你帮她切肉,你妈妈上午要出门有点事,同时不巧呢,你老婆说她上午也要出门,让你帮着打扫家里卫生,这时你今天就要同时做三件事,看比赛,切肉,打扫卫生.这

【专家坐堂】四种并发编程模型简介

本文来自网易云社区 概述 并发往往和并行一起被提及,但是我们应该明确的是"并发"不等同于"并行" ?       并发 :同一时间 对待 多件事情 (逻辑层面) ?       并行 :同一时间 做(执行) 多件事情 (物理层面) 并发可以构造出一种问题解决方法,该方法能够被用于并行化,从而让原本只能串行处理的事务并行化,更好地发挥出当前多核CPU,分布式集群的能力. 但是,并发编程和人们正常的思维方式是不一样的,因此才有了各种编程模型的抽象来帮助我们更方便,更不容

两种并发安全链表的实现和对比

多核处理器日益普及的现在很多代码都得和并发/并行打交道,对于内置了并发支持(goroutine)的golang来说并发编程是必不可少的一环. 链表是我们再熟悉不过的数据结构,在并发编程中我们也时长需要用到,今天我们就来看两种带锁的并发安全的单项链表. 方案一:粗粒度锁,完全锁住链表 方案一的做法是将所有操作用锁--Mutex串行化处理.串行化处理是指锁和链表相关联,当需要修改或读取链表时就获取锁,只要该goroutine持有锁,那么其他goroutine就无法修改或读取链表,直到锁的持有者将其释

程序员必知的七种并发编程模型

1.线程与锁线程与锁模型有很多众所周知的不足,但仍是其他模型的技术基础,也是很多并发软件开发的首选. 2.函数式编程 函数式编程日渐重要的原因之一,是其对并发编程和并行编程提供了良好的支持.函数式编程消除了可变状态,所以从根本上是线程安全的,而且易于并行执行. 3.Clojure之道——分离标识与状态 编程语言Clojure是一种指令式编程和函数式编程的混搭方案,在两种编程方式上取得了微妙的平衡来发挥两者的优势. 4.actor actor模型是一种适用性很广的并发编程模型,适用于共享内存模型和

golang常见的几种并发模型框架

原文链接 package main import ( "fmt" "math/rand" "os" "runtime" "sync" "sync/atomic" "time" ) type Scenario struct { Name string Description []string Examples []string RunExample func() } v