使用select方式实现一个C/S架构的应用; 要求:服务器同时支持多个客户端连接,一个客户端发送消息,服务器回复 一个XML消息(内容不限);
时间: 2023-06-23 15:09:10 浏览: 117
以下是使用select方式实现C/S架构应用的代码示例:
服务器端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#define MAX_CLIENTS 5
#define BUFFER_SIZE 1024
int main(int argc, char *argv[])
{
int server_fd, client_fds[MAX_CLIENTS], max_fd, activity, i, valread;
struct sockaddr_in server_addr, client_addr;
char buffer[BUFFER_SIZE] = {0};
fd_set read_fds;
// 创建服务器socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置服务器socket的地址和端口号
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(atoi(argv[1]));
// 绑定服务器socket
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听服务器socket
if (listen(server_fd, MAX_CLIENTS) < 0)
{
perror("listen failed");
exit(EXIT_FAILURE);
}
printf("Server is listening on port %d.\n", atoi(argv[1]));
// 初始化客户端socket数组
for (i = 0; i < MAX_CLIENTS; i++)
{
client_fds[i] = 0;
}
while (1)
{
// 清空文件描述符集
FD_ZERO(&read_fds);
// 将服务器socket加入文件描述符集
FD_SET(server_fd, &read_fds);
max_fd = server_fd;
// 将所有已连接的客户端socket加入文件描述符集
for (i = 0; i < MAX_CLIENTS; i++)
{
int fd = client_fds[i];
if (fd > 0)
{
FD_SET(fd, &read_fds);
if (fd > max_fd)
{
max_fd = fd;
}
}
}
// 监听文件描述符集上的事件
activity = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
if ((activity < 0) && (errno != EINTR))
{
printf("select error");
}
// 处理服务器socket上的连接请求
if (FD_ISSET(server_fd, &read_fds))
{
int new_socket, addr_len = sizeof(client_addr);
if ((new_socket = accept(server_fd, (struct sockaddr *)&client_addr, (socklen_t *)&addr_len)) < 0)
{
perror("accept failed");
exit(EXIT_FAILURE);
}
printf("New client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
// 将新连接的客户端socket加入客户端socket数组
for (i = 0; i < MAX_CLIENTS; i++)
{
if (client_fds[i] == 0)
{
client_fds[i] = new_socket;
break;
}
}
}
// 处理客户端socket上的消息
for (i = 0; i < MAX_CLIENTS; i++)
{
int fd = client_fds[i];
if (FD_ISSET(fd, &read_fds))
{
if ((valread = read(fd, buffer, BUFFER_SIZE)) == 0)
{
// 客户端断开连接,将其socket从客户端socket数组中移除
close(fd);
client_fds[i] = 0;
printf("Client disconnected.\n");
}
else
{
// 处理客户端发送的消息
printf("Received message from client: %s\n", buffer);
// 回复XML消息给客户端
char *xml_message = "<message>XML message</message>";
send(fd, xml_message, strlen(xml_message), 0);
}
}
}
}
return 0;
}
```
客户端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
int main(int argc, char *argv[])
{
int client_fd, valread;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE] = {0};
// 创建客户端socket
if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置服务器socket的地址和端口号
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
server_addr.sin_port = htons(atoi(argv[2]));
// 连接服务器socket
if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("connect failed");
exit(EXIT_FAILURE);
}
printf("Connected to server: %s:%d\n", argv[1], atoi(argv[2]));
// 发送消息给服务器
char *message = "Hello server!";
send(client_fd, message, strlen(message), 0);
printf("Sent message to server: %s\n", message);
// 接收服务器回复的消息
valread = read(client_fd, buffer, BUFFER_SIZE);
printf("Received message from server: %s\n", buffer);
close(client_fd);
return 0;
}
```
服务器端使用了select函数来同时处理多个客户端连接,客户端连接时会发送Hello server!消息给服务器,服务器会回复一个XML消息。
阅读全文