几种并发服务器模型的实现:多线程,多进程,select,poll,epoll
http://www.cnblogs.com/wj9012/p/3879605.html
客户端使用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 }
几种并发服务器模型的实现:多线程,多进程,select,poll,epoll相关推荐
- 五种高级IO | select poll epoll 水平触发模式 边缘触发模式 惊群问题
一.高级IO 在介绍多路复用IO之前,先介绍一下其它四种高级IO: 阻塞IO: 在内核将数据准备好之前,系统调用会一直等待.所以的套集字默认是阻塞方式. 非阻塞IO: 在内核还未将数据准备好,则系统调 ...
- step5 . day6 网络编程 基于TCP协议的多并发模式(使用多进程、多线程、select函数分别实现)...
实现TCP服务器端多路并发的方法有①多进程②多线程③IO多路复用(select poll epoll函数) 1.多进程实现并发模式(仅在服务器端更改之前代码实现) 服务器端 #include < ...
- 《嵌入式系统 – 玩转ART-Pi开发板(基于RT-Thread系统)》第9章 基于Select/Poll实现并发服务器(二)
基于Select/Poll实现并发服务器(一) 9.3 Select/Poll概述 在LWIP中,如果要实现并发服务器,可以基于Sequentaial API来实现,这种方式需要使用多线程,也就是为每 ...
- 服务器编程入门(11)TCP并发回射服务器实现 - 单线程select实现
问题聚焦: 当客户端阻塞于从标准输入接收数据时,将读取不到别的途径发过来的必要信息,如TCP发过来的FIN标志. 因此,进程需要内核一旦发现进程指定的一个或多个IO条件就绪(即输入已准备好被读取,或者 ...
- Linux服务器 | 服务器模型与三个模块、两种并发模式:半同步/半异步、领导者/追随者
文章目录 两种服务器模型及三个模块 C/S模型 P2P模型 I/O处理单元.逻辑单元.存储单元 并发 同步与异步 半同步/半异步模式 变体:半同步/半反应堆模式 改进:高效的半同步/半异步模式 领导者 ...
- 0730------Linux网络编程----------服务器端模型(迭代,多进程,多线程,select,poll,epoll 等)...
1.迭代服务器模型 1.1 迭代服务器是处理多个请求时一种最简单直接的思路,即使用while循环,它不具有并发能力,即必须一个一个的处理客户的请求. 1.2 程序示例. #include " ...
- python支持的几种并发方式进行简单的总结
本文对python支持的几种并发方式进行简单的总结. Python支持的并发分为多线程并发与多进程并发(异步IO本文不涉及).概念上来说,多进程并发即运行多个独立的程序,优势在于并发处理的任务都由操作 ...
- 多线程,多进程选择(了解)
鱼还是熊掌:浅谈多进程多线程的选择 关于多进程和多线程,教科书上最经典的一句话是"进程是资源分配的最小单位,线程是CPU调度的最小单位",这句话应付考试基本上够了,但如果在工作中遇 ...
- 创建三个并发进程linux,Linux下几种并发服务器的实现模式(详解)
1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循 ...
最新文章
- Oracle For Linux安装脚本
- 炫“库”行动-人大金仓征文大赛—数据领域“新·独角兽”
- luogu1347 排序
- 【windows环境——VSCode安装教程】
- 求两个点的欧氏距离_数据智能系列(五)| 距离的秘密
- Spring Cloud微服务分布式云架构源码结构
- 怎么做好企业网站关键词优化
- spss数据预处理步骤_Spss的数据预处理
- 全民K歌神器,这款麦克风唱享高音质体验
- %1 不是有效的 Win32 应用程序
- 电信设备商进入企业网市场需适应不同渠道模式(转载)
- 定时线程池实现请求合并
- 等本等息,等额本息,等额本金,看懂再贷款,坑多!
- Window系统上的Nacos安装与配置
- 宇视摄像机巡航和自动跟踪哪个优先级高?
- 使用F12下载GoToMeeting上录播的方法
- linux终端能不能打字,不能打字只有拼音_Ubuntu系统拼音无法正确打字怎么解决
- VMware NAT 模式,网关无法ping通 网关解决办法
- nginx配置https证书、https数字证书申请
- sln和.csproj的区别
热门文章
- 二分+树的直径 [Sdoi2011]消防
- Hibernate 基础配置及常用功能(二)
- 棋牌游戏服务器架构: 详细设计(三) 数据库设计
- 内核编译配置选项含义
- mac安装了多版本php 卸载,mac 安装多版本PHP
- 华为摄像机搜索软件_别人的终点华为的起点!用普惠AI守护城市安全
- 怎么通过media foundation将图像数据写入虚拟摄像头_千倍成本压缩!特斯拉开发虚拟激光雷达,替代最贵自动驾驶传感器...
- 28岁学python转行_28岁转行程序员,学Java还是Python?码农:想快点月薪过万就选它...
- oracle symonym_ORACLE SYNONYM详解
- html文档主体的根标签,2 HTML简介标签嵌套和并列关系文档声明