用c语言写一个程序:综合系统功能要求:模拟KTV点歌系统,具体功能参照下图需要重点考虑的问题:(1)歌曲该以怎样的数据结构进行存储;(2)如何支持查询功能;(3)如何基于socket实现client与server的消息交互;
时间: 2024-05-12 16:12:59 浏览: 148
以下是一个简单的用C语言实现KTV点歌系统的程序。该程序使用链表数据结构存储歌曲信息,支持查询功能,并基于socket实现client与server的消息交互。
```
/********** KTV点歌系统 **********/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8080
/********** 数据结构 **********/
typedef struct Song {
int id;
char name[100];
char singer[100];
struct Song *next;
} Song;
Song *head = NULL;
/********** 函数声明 **********/
void addSong(int id, char name[], char singer[]);
void displaySongs();
Song *findSong(int id);
void handleClient(int socket);
/********** 主函数 **********/
int main() {
int serverSocket, clientSocket;
struct sockaddr_in serverAddr, clientAddr;
socklen_t addrLen = sizeof(struct sockaddr_in);
// 创建socket
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
printf("创建socket失败\n");
exit(1);
}
// 绑定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)) == -1) {
printf("绑定socket到端口失败\n");
exit(1);
}
// 监听socket
if (listen(serverSocket, 5) == -1) {
printf("监听socket失败\n");
exit(1);
}
printf("KTV点歌系统已启动,等待客户端连接...\n");
// 接受客户端连接请求
while ((clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &addrLen))) {
printf("客户端 %s:%d 已连接\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
// 处理客户端请求
handleClient(clientSocket);
// 关闭客户端socket
close(clientSocket);
printf("客户端 %s:%d 已断开连接\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
}
// 关闭服务器socket
close(serverSocket);
printf("KTV点歌系统已关闭\n");
return 0;
}
/********** 函数实现 **********/
// 添加歌曲
void addSong(int id, char name[], char singer[]) {
Song *newSong = (Song *)malloc(sizeof(Song));
newSong->id = id;
strcpy(newSong->name, name);
strcpy(newSong->singer, singer);
newSong->next = NULL;
if (head == NULL) {
head = newSong;
} else {
Song *currentSong = head;
while (currentSong->next != NULL) {
currentSong = currentSong->next;
}
currentSong->next = newSong;
}
printf("已添加歌曲 %d - %s (%s)\n", id, name, singer);
}
// 显示所有歌曲
void displaySongs() {
if (head == NULL) {
printf("暂无歌曲\n");
} else {
printf("编号\t歌曲名\t\t\t歌手\n");
printf("=============================================\n");
Song *currentSong = head;
while (currentSong != NULL) {
printf("%d\t%s\t\t%s\n", currentSong->id, currentSong->name, currentSong->singer);
currentSong = currentSong->next;
}
}
}
// 根据id查找歌曲
Song *findSong(int id) {
Song *currentSong = head;
while (currentSong != NULL) {
if (currentSong->id == id) {
return currentSong;
}
currentSong = currentSong->next;
}
return NULL;
}
// 处理客户端请求
void handleClient(int socket) {
char buffer[1024] = {0};
char response[1024] = {0};
int valread;
while (1) {
// 读取客户端消息
valread = read(socket, buffer, 1024);
if (valread == 0) {
break;
}
// 处理客户端请求
if (strcmp(buffer, "add") == 0) {
int id;
char name[100], singer[100];
memset(buffer, 0, sizeof(buffer));
read(socket, buffer, 1024);
id = atoi(buffer);
memset(buffer, 0, sizeof(buffer));
read(socket, buffer, 1024);
strcpy(name, buffer);
memset(buffer, 0, sizeof(buffer));
read(socket, buffer, 1024);
strcpy(singer, buffer);
addSong(id, name, singer);
strcpy(response, "OK");
} else if (strcmp(buffer, "display") == 0) {
displaySongs();
strcpy(response, "OK");
} else if (strcmp(buffer, "find") == 0) {
int id;
Song *song;
memset(buffer, 0, sizeof(buffer));
read(socket, buffer, 1024);
id = atoi(buffer);
song = findSong(id);
if (song != NULL) {
sprintf(response, "歌曲信息:%d - %s (%s)", song->id, song->name, song->singer);
} else {
sprintf(response, "找不到编号为 %d 的歌曲", id);
}
} else if (strcmp(buffer, "exit") == 0) {
strcpy(response, "Bye");
break;
} else {
strcpy(response, "Invalid Command");
}
// 发送响应消息给客户端
send(socket, response, strlen(response), 0);
memset(buffer, 0, sizeof(buffer));
memset(response, 0, sizeof(response));
}
}
```
该程序中,歌曲信息使用链表数据结构存储,每个歌曲包含编号、歌曲名、歌手三个属性。
在主函数中,首先创建一个socket,然后绑定到端口,并开始监听客户端连接请求。每当有客户端连接成功时,就会调用handleClient函数来处理客户端请求。
handleClient函数中,首先从客户端读取消息,然后根据消息类型调用相应的函数来处理请求。如果是添加歌曲请求,则读取歌曲的编号、歌曲名和歌手信息,并调用addSong函数来添加歌曲。如果是显示所有歌曲请求,则调用displaySongs函数来显示所有歌曲。如果是查找歌曲请求,则读取歌曲编号,并调用findSong函数来查找歌曲。如果是退出请求,则退出循环,并发送"Bye"响应消息给客户端。如果是无效请求,则发送"Invalid Command"响应消息给客户端。
在处理完客户端请求后,handleClient函数会清空buffer和response数组,并继续等待下一个客户端请求。
客户端与server的消息交互基于socket实现,客户端使用TCP协议连接到服务器端口,并发送请求消息。服务器接收客户端消息,并根据消息类型返回响应消息。客户端接收响应消息并显示在屏幕上。
阅读全文