一、概述
本攻略将详细讲解使用多进程实现Linux服务器并发访问的过程,具体涉及整体架构、代码实现以及代码调试等方面。该方法具有较高的灵活性和扩展性,适用于实现高并发,高可靠的服务器。
二、整体架构
多进程实现服务器并发访问的整体架构如下:
-
父进程负责创建并监听服务端socket,接收客户端的连接请求。
-
当有客户端连接请求到达时,父进程fork一个子进程,由该子进程与客户端进行数据交互。
-
如有需要,子进程可再次fork新的子进程,实现进一步的并发处理。
-
父进程负责回收已经处理完毕的子进程,防止出现“僵尸进程”。
三、代码实现
以下是一个简单的多进程服务器实现代码示例。
- 服务端代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#define PORT 8888
#define MAX_BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
int serverSocket, clientSocket, pid, readSize;
struct sockaddr_in serverAddr, clientAddr;
socklen_t addrLen = sizeof(clientAddr);
char buffer[MAX_BUFFER_SIZE] = {0};
// 创建服务端socket
if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Failed to create socket");
exit(EXIT_FAILURE);
}
// 绑定socket到指定地址和端口
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(PORT);
if (bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {
perror("Failed to bind");
exit(EXIT_FAILURE);
}
// 开始监听连接请求
if (listen(serverSocket, 5) < 0) {
perror("Failed to listen");
exit(EXIT_FAILURE);
}
printf("Server is listening on port %d\n", PORT);
// 接收连接请求并处理
while (1) {
if ((clientSocket = accept(serverSocket, (struct sockaddr *) &clientAddr, &addrLen)) < 0) {
perror("Failed to accept");
exit(EXIT_FAILURE);
}
// 父进程fork一个子进程处理连接请求
if ((pid = fork()) < 0) {
perror("Failed to fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
close(serverSocket); // 关闭父进程的监听socket
printf("Client %s:%d is connected\n", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port);
while((readSize = read(clientSocket, buffer, MAX_BUFFER_SIZE)) > 0) {
printf("Received message from client %s:%d: %s", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port, buffer);
write(clientSocket, "Server received your message", strlen("Server received your message"));
memset(buffer, 0, MAX_BUFFER_SIZE);
}
printf("Client %s:%d disconnected\n", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port);
close(clientSocket); // 关闭子进程的socket
exit(EXIT_SUCCESS); // 终止子进程
} else {
close(clientSocket); // 关闭父进程对应客户端的连接
}
}
return 0;
}
- 客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define SERVER_ADDR "127.0.0.1"
#define PORT 8888
#define MAX_BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
int clientSocket;
struct sockaddr_in serverAddr;
char buffer[MAX_BUFFER_SIZE] = {0};
// 创建客户端socket
if ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Failed to create socket");
exit(EXIT_FAILURE);
}
// 设置服务端地址和端口
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
if (inet_pton(AF_INET, SERVER_ADDR, &serverAddr.sin_addr) <= 0) {
perror("Invalid address/ Address not supported");
exit(EXIT_FAILURE);
}
// 连接服务端
if (connect(clientSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {
perror("Failed to connect");
exit(EXIT_FAILURE);
}
// 发送消息
while (fgets(buffer, MAX_BUFFER_SIZE, stdin) != NULL) {
send(clientSocket, buffer, strlen(buffer), 0);
memset(buffer, 0, MAX_BUFFER_SIZE);
recv(clientSocket, buffer, MAX_BUFFER_SIZE, 0);
printf("%s\n", buffer);
}
// 关闭客户端socket
close(clientSocket);
return 0;
}
四、代码调试
要在Linux环境下运行代码,可以使用gcc编译器进行编译,命令如下:
gcc -o server server.c
gcc -o client client.c
然后分别运行server和client可执行文件即可。
在运行过程中,可以使用netstat命令查看服务端监听的地址和端口,命令如下:
netstat -an | grep LISTEN
可以在客户端输入消息并发送,观察服务端是否正确接收并处理消息。
五、示例说明
- 实现FTP服务器。
在FTP服务器中,要求支持多个用户同时连接,对于每个用户的请求都进行互相独立的处理。使用多进程可以很方便地实现这个需求。
- 实现Web服务器。
Web服务器要求在高并发的情况下为客户端提供服务,使用多进程能方便地进行并发处理,提高服务器的并发能力和稳定性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Linux网络编程使用多进程实现服务器并发访问 - Python技术站