欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > UDP并发服务器之多进程并发

UDP并发服务器之多进程并发

2025/4/3 1:49:41 来源:https://blog.csdn.net/2401_85344823/article/details/146673428  浏览:    关键词:UDP并发服务器之多进程并发

一、常见的服务器类型


在网络程序里面,通常都是一个服务器处理多个客户端。为了处理多个客户端的请求, 服务器端程序有不同的处理方式。

1. 迭代服务器

大多数UDP都是迭代运行,服务器等待客户端的数据,收到数据后处理该数据,送回其应答,在等待下一个客户端请求。

 

2. 并发服务器

  • 并发服务器是指在同一个时刻可以响应多个客户端的请求
  • 本质是创建 多进程/多线程 ,对多数用户的信息进行处理
  • UDP协议一般默认是不支持多线程并发的 ,因为默认UDP服务器只有一个sockfd,所有的客户端都是通过同一个sockfd进行通信的。udp使用一个socket,如何做到做并发呢?

 

 3. UDP并发服务器使用的场景

当UDP协议针对客户请求的处理需要消耗过长的时间时,我们期望UDP服务器具有某种形式的并发性。


二、UDP多进程并发服务器


1. 场景设计

多个udp客户端需要先验证密钥是否正确后,才允许进行数据交互。假设密钥为"root"。(类似于登录功能)服务器接收到客户端信息,需要考虑两种情况<1>A用户的密钥验证请求消息<2>B用户的数据交互接收消息

2. 框架图
 

 

 3. 使用场景

当UDP服务器与客户端交互多个数据报。问题在于每个客户都是往服务器端的同一个的端口发送数据,并用的同一个sockfd。并发服务器的每一个子进程如何正确区分每一个客户的数据报(涉及到进程的调度问题,如何避免一个子进程读取到不该它服务的客户发送来的数据报)。

解决的方法是服务器(知名端口)等待客户的到来,当一个客户到来后,记下其IP和port,然后服务器fork一个子进程,建立一个socket再bind一个随机端口,然后建立与客户端的连接,并处理该客户的请求。父进程继续循环,等待下一个客户的到来。 在tftpd中就是使用这种技术的 。

 

UDP并发服务器的多进程并发是一种常见的并发处理方式,通过为每个客户端请求创建一个独立的子进程来实现并发处理。以下是关于UDP并发服务器多进程并发的详细讲解:

三、

1. 基本原理

UDP是一种无连接的协议,数据包独立发送,服务器不需要维护与客户端的长期连接。在多进程并发模型中,父进程负责监听UDP端口,接收客户端的请求,然后为每个请求创建一个子进程来处理具体的通信。

2. 实现步骤

(1)父进程初始化

父进程创建一个UDP套接字,并绑定到指定的IP地址和端口。然后进入循环,等待客户端的请求

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));

 

2)接收请求并创建子进程

父进程接收客户端发送的数据包,然后通过fork()创建一个子进程来处理该请求

 

while(1) {struct sockaddr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);char buffer[1024];int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&client_addr, &client_addr_len);if(n > 0) {pid_t pid = fork();if(pid == 0) { // 子进程close(sockfd); // 子进程关闭父进程的套接字// 子进程处理客户端请求handle_request(buffer, client_addr, client_addr_len);exit(0);}}
}

 

(3)子进程处理请求

子进程接收父进程传递的客户端信息后,使用自己的套接字与客户端进行通信

void handle_request(char* buffer, struct sockaddr_in client_addr, socklen_t client_addr_len) {int new_sockfd = socket(AF_INET, SOCK_DGRAM, 0);// 子进程绑定到一个新的端口struct sockaddr_in new_server_addr;memset(&new_server_addr, 0, sizeof(new_server_addr));new_server_addr.sin_family = AF_INET;new_server_addr.sin_port = htons(0); // 系统自动分配端口new_server_addr.sin_addr.s_addr = INADDR_ANY;bind(new_sockfd, (struct sockaddr*)&new_server_addr, sizeof(new_server_addr));// 向客户端发送响应sendto(new_sockfd, "Hello from server", 18, 0, (struct sockaddr*)&client_addr, client_addr_len);close(new_sockfd);
}

 

3. 优点

  • 简单易实现:多进程模型相对简单,易于理解和实现。

  • 资源隔离:每个子进程独立运行,互不干扰,即使一个子进程崩溃,也不会影响其他子进程。

4. 缺点

  • 进程创建开销大:每次创建子进程都需要消耗系统资源,频繁创建和销毁进程可能导致性能下降。

  • 资源占用高:每个子进程都需要占用一定的系统资源,包括内存和文件描述符。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词