企业网站推广方案范文,深圳网站建设公司怎么做,长沙公司网站设计报价,青岛微网站一.多进程并发服务器
多进程并发服务器是一种经典的服务器架构#xff0c;它通过创建多个子进程来处理客户端连接#xff0c;从而实现并发处理多个客户端请求的能力。
概念#xff1a;
服务器启动时#xff0c;创建主进程#xff0c;并绑定监听端口。当有客户端连接请求…
一.多进程并发服务器
多进程并发服务器是一种经典的服务器架构它通过创建多个子进程来处理客户端连接从而实现并发处理多个客户端请求的能力。
概念
服务器启动时创建主进程并绑定监听端口。当有客户端连接请求时主进程接受连接并创建一个子进程来处理该客户端连接。子进程与客户端进行通信处理请求和发送响应。主进程继续监听新的连接请求。子进程完成任务后可以选择终止或继续处理其他连接根据需求选择是否重复循环。
优点
高并发处理能力每个子进程都可以独立地处理一个客户端连接利用多核处理器的优势实现高并发处理能力提高服务器的吞吐量。稳定性每个子进程都是独立的一个进程出现问题不会影响其他进程提高了服务器的稳定性和容错能力。简单直观采用多进程模型实现并发服务器相对简单代码可读性高易于理解和维护。跨平台多进程并发服务器概念适用于各种操作系统不仅限于Linux平台。
缺点
高资源消耗每个子进程都需要独立的资源包括内存、文件描述符等当并发连接数较高时会消耗大量的系统资源。进程间通信各个子进程之间的通信需要额外的机制例如管道、共享内存等增加了复杂性。上下文切换开销进程间切换的开销相对较大会影响性能。调试困难由于每个子进程独立执行调试和定位问题可能会变得复杂。
综上所述多进程并发服务器能够满足高并发处理需求并具有稳定性和简单性等优点。然而它也存在资源消耗较高和调试困难等缺点根据实际需求和应用场景选择合适的服务器架构是很重要的。
案例 利用多进程在TCP通信的基础上实现服务器可以同时连接多个客户端。实现大小写转换。 service.c
#include stdio.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include netinet/ip.h
#include arpa/inet.h
#include string.h
#include stdlib.h
#include unistd.h
#include signal.h
#include sys/wait.hvoid handler(int sig)
{if (sig SIGCHLD){while(waitpid(0,NULL,WNOHANG)0);}
}
int main(int argc, char const *argv[])
{//1.建立socket套接字int socked socket(AF_INET, SOCK_STREAM, 0);if (socked 0){perror(socket is err);return -1;}//2.bind绑定服务器ip和端口号struct sockaddr_in saddr, caddr;saddr.sin_family AF_INET;saddr.sin_port htons(atoi(argv[1]));saddr.sin_addr.s_addr inet_addr(0.0.0.0);int len sizeof(caddr);int rev bind(socked, (struct sockaddr *)(saddr), sizeof(saddr));if (rev 0){perror(bind is err);return 0;}//3.listen设置最大同时链接数量rev listen(socked, 32);if (rev 0){perror(rev is err);return 0;}//4.建立子进程负责服务器给客户端发送消息,并且主进程不结束,此进程不结束char buf[1024] {0};int size0;while (1){int acceptfd accept(socked, (struct sockaddr *)(caddr), len);if (acceptfd 0){perror(accept is err);return 0;}pid_t pid fork();if (pid 0){perror(pid is err);return 0;}else if (pid 0){//子进程,每个子进程维护一个客户端//不许要监听,直接关掉close(socked);while (1){int flage recv(acceptfd, buf, sizeof(buf), 0);if (flage 0){perror(recv is err);}else if (flage 0){printf(ip:%s is close\n, inet_ntoa(caddr.sin_addr));close(acceptfd);break;}else{size strlen(buf);for (int i 0; i size; i){if (buf[i] a buf[i] z)buf[i] buf[i] (A - a);elsebuf[i] buf[i] (a - A);}printf(%d %s\n,getpid(),buf);send(acceptfd, buf, sizeof(buf), 0);}}}else{//主进程回收子线程资源close(acceptfd);//异步节约资源signal(SIGCHLD, handler);}}return 0;
}client.c
#include stdio.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include netinet/ip.h
#include arpa/inet.h
#include string.h
#include stdlib.h
#include unistd.hint main(int argc, char const *argv[])
{//1.socket建立文件描述符int fd socket(AF_INET, SOCK_STREAM, 0);if (fd 0){perror(socket is err);}//2.connect连接服务器struct sockaddr_in saddr;saddr.sin_family AF_INET;saddr.sin_port htons(atoi(argv[2]));saddr.sin_addr.s_addr inet_addr(argv[1]);int flage connect(fd, (struct sockaddr *)(saddr), sizeof(saddr));if (flage 0){perror(connect is err);}//3.服务器端不断发送数据,接受服务器转化后的数据char buf[1024] {0};while (1){//memset(buf,0,sizeof(buf));fgets(buf, sizeof(buf), stdin);if (strncmp(buf,quit#,5)0){break;}if (buf[strlen(buf) - 1] \n)buf[strlen(buf) - 1] \0;send(fd, buf, sizeof(buf), 0);flage recv(fd, buf, sizeof(buf), 0);if (flage 0){perror(recv is err);}else{fprintf(stdout, %s\n, buf);}}close(fd);return 0;
}二.多线程并发服务器
多线程并发服务器是一种服务器架构通过创建多个线程来处理客户端连接实现并发处理多个客户端请求的能力。下面是多线程并发服务器的概念和一些优点
概念
服务器启动时创建主线程并绑定监听端口。当有客户端连接请求时主线程接受连接并创建一个或多个线程来处理该客户端连接。线程与客户端进行通信处理请求和发送响应。主线程继续监听新的连接请求。线程完成任务后选择终止或继续处理其他连接根据需求选择是否重复循环。
优点
资源效率线程相比进程创建和销毁的开销较小占用的资源较少特别是共享的资源如文件描述符可以在多个连接之间共享提高了资源的利用效率。响应速度线程之间的切换开销较小内存空间共享可以快速响应客户端请求减少了连接等待时间。简单直观与多进程相比多线程实现并发服务器更简单直观代码可读性高易于理解和维护。可扩展性线程可轻松地添加和删除适应不断变化的连接数需求提供更好的可扩展性。共享数据简便线程之间共享的数据结构可以直接访问不需要像进程间通信一样使用额外的机制。
缺点
数据同步问题多线程共享数据可能导致竞态条件和数据一致性问题需要使用锁或其他同步机制来保证线程安全。调试困难由于线程之间共享同一进程的内存空间调试和定位问题可能会变得复杂。并行性限制在某些情况下多线程服务器的并行性可能受限于系统中可用的CPU核心数量。需要考虑线程安全编写线程安全的代码可能需要更多的开发工作和考虑避免数据竞争和死锁等问题。
综上所述多线程并发服务器能够满足高并发处理需求并具有资源效率、响应速度、简单性和可扩展性等优点。然而它也存在数据同步问题和调试困难等缺点根据实际需求和应用场景选择合适的服务器架构是很重要的。
案例 利用多线程在TCP通信的基础上实现服务器可以同时连接多个客户端。实现大小写转换。 service.c
#include stdio.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include netinet/ip.h
#include arpa/inet.h
#include string.h
#include stdlib.h
#include unistd.h
#include signal.h
#include sys/wait.h
#include pthread.hstruct client
{int acceptfd;struct sockaddr_in caddr;
};void *my_pthread(void *p)
{char buf[1024] {0};int size 0;struct client *cl (struct client *)p;int acceptfd cl-acceptfd;struct sockaddr_in caddr cl-caddr;while (1){int flage recv(acceptfd, buf, sizeof(buf), 0);if (flage 0){perror(recv is err);}else if (flage 0){printf(ip:%s is close\n, inet_ntoa(caddr.sin_addr));close(acceptfd);break;}else{size strlen(buf);for (int i 0; i size; i){if (buf[i] a buf[i] z)buf[i] buf[i] (A - a);elsebuf[i] buf[i] (a - A);}send(acceptfd, buf, sizeof(buf), 0);}}close(acceptfd);return 0;
}int main(int argc, char const *argv[])
{//1.建立socket套接字int socked socket(AF_INET, SOCK_STREAM, 0);if (socked 0){perror(socket is err);return -1;}//2.bind绑定服务器ip和端口号struct sockaddr_in saddr, caddr;saddr.sin_family AF_INET;saddr.sin_port htons(atoi(argv[1]));saddr.sin_addr.s_addr inet_addr(0.0.0.0);int len sizeof(caddr);int rev bind(socked, (struct sockaddr *)(saddr), sizeof(saddr));if (rev 0){perror(bind is err);return 0;}//3.listen设置最大同时链接数量rev listen(socked, 32);if (rev 0){perror(rev is err);return 0;}//4.建立子进程负责服务器给客户端发送消息,并且主进程不结束,此进程不结束int i 0;pthread_t tid;struct client ti[1024] {0};while (1){int acceptfd accept(socked, (struct sockaddr *)(caddr), len);if (acceptfd 0){perror(accept is err);return 0;}ti[i].acceptfd acceptfd;ti[i].caddr caddr;pthread_create(tid, NULL, my_pthread, (void *)ti[i]);pthread_detach(tid);i;}return 0;
}client.c
#include stdio.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include netinet/ip.h
#include arpa/inet.h
#include string.h
#include stdlib.h
#include unistd.hint main(int argc, char const *argv[])
{//1.socket建立文件描述符int fd socket(AF_INET, SOCK_STREAM, 0);if (fd 0){perror(socket is err);}//2.connect连接服务器struct sockaddr_in saddr;saddr.sin_family AF_INET;saddr.sin_port htons(atoi(argv[2]));saddr.sin_addr.s_addr inet_addr(argv[1]);int flage connect(fd, (struct sockaddr *)(saddr), sizeof(saddr));if (flage 0){perror(connect is err);}//3.服务器端不断发送数据,接受服务器转化后的数据char buf[1024] {0};while (1){//memset(buf,0,sizeof(buf));fgets(buf, sizeof(buf), stdin);if (strncmp(buf,quit#,5)0){break;}if (buf[strlen(buf) - 1] \n)buf[strlen(buf) - 1] \0;send(fd, buf, sizeof(buf), 0);flage recv(fd, buf, sizeof(buf), 0);if (flage 0){perror(recv is err);}else{fprintf(stdout, %s\n, buf);}}close(fd);return 0;
}