#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define BUF_SIZE 1024
#define MAX_SINGERS 100
void error_handling(char *message);
// 가수와 노래 정보를 저장하는 구조체
typedef struct {
char singer[BUF_SIZE];
char songs[BUF_SIZE];
} SingerSongs;
int find_singer(SingerSongs singers[], int count, char *singer_name);
void add_singer(SingerSongs singers[], int *count, char *singer_name, char *songs);
int main(int argc, char *argv[]) {
int serv_sock, clnt_sock;
char message[BUF_SIZE];
int str_len;
char singer_name[BUF_SIZE];
char songs[BUF_SIZE];
int singer_count = 6; // 기본적으로 저장된 가수 수
SingerSongs singers[MAX_SINGERS] = { // 초기 가수와 노래 목록
{"newjeans", "cookies, hypeboy, attention"},
{"blackpink", "shutdown, icecream, stay"},
{"ive", "eleven, love dive, afterlike"},
{"kara", "honey, step, rock u"},
{"idle", "tomboy, nude, my bag"},
{"bts", "butter, dna, yet to come"}
};
struct sockaddr_in serv_adr, clnt_adr;
socklen_t clnt_adr_sz;
if (argc != 2) {
printf("Usage: %s <port>\\n", argv[0]);
exit(1);
}
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if (serv_sock == -1)
error_handling("socket() error");
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_adr.sin_port = htons(atoi(argv[1]));
if (bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1)
error_handling("bind() error");
if (listen(serv_sock, 5) == -1)
error_handling("listen() error");
clnt_adr_sz = sizeof(clnt_adr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
if (clnt_sock == -1)
error_handling("accept() error");
while (1) {
// 클라이언트로부터 가수 이름 받기
read(clnt_sock, singer_name, BUF_SIZE);
singer_name[strcspn(singer_name, "\\n")] = 0; // 개행 문자 제거
// 'q' 입력 시 종료
if (!strcmp(singer_name, "q") || !strcmp(singer_name, "Q")) {
break;
}
// 가수가 이미 저장되어 있으면 노래 목록을 반환
int idx = find_singer(singers, singer_count, singer_name);
if (idx != -1) {
write(clnt_sock, singers[idx].songs, BUF_SIZE);
} else {
// 가수가 없으면 클라이언트로부터 새로운 노래 목록을 입력받음
write(clnt_sock, "Singer not found. Please provide songs for this singer:\\n", BUF_SIZE);
read(clnt_sock, songs, BUF_SIZE);
songs[strcspn(songs, "\\n")] = 0; // 개행 문자 제거
// 새로운 가수와 노래 목록을 저장
add_singer(singers, &singer_count, singer_name, songs);
write(clnt_sock, "New singer and songs added successfully.\\n", BUF_SIZE);
}
}
close(clnt_sock);
close(serv_sock);
return 0;
}
void error_handling(char *message) {
fputs(message, stderr);
fputc('\\n', stderr);
exit(1);
}
// 가수를 찾는 함수 (없으면 -1 반환)
int find_singer(SingerSongs singers[], int count, char *singer_name) {
for (int i = 0; i < count; i++) {
if (strcmp(singers[i].singer, singer_name) == 0) {
return i;
}
}
return -1;
}
// 새로운 가수와 노래를 추가하는 함수
void add_singer(SingerSongs singers[], int *count, char *singer_name, char *songs) {
if (*count < MAX_SINGERS) {
strcpy(singers[*count].singer, singer_name);
strcpy(singers[*count].songs, songs);
(*count)++;
} else {
printf("Cannot add more singers, maximum limit reached.\\n");
}
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define BUF_SIZE 1024
void error_handling(char *message);
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in serv_addr;
char message[BUF_SIZE];
int str_len;
char singer_name[BUF_SIZE];
if (argc != 3) {
printf("Usage: %s <IP> <port>\\n", argv[0]);
exit(1);
}
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1)
error_handling("socket() error");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(atoi(argv[2]));
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
error_handling("connect() error");
while (1) {
// 사용자로부터 가수 이름 입력받기
printf("Input singer (or 'q' to quit): ");
fgets(singer_name, BUF_SIZE, stdin);
// 서버로 가수 이름 전송
write(sock, singer_name, strlen(singer_name));
// 'q'를 입력하면 종료
if (!strcmp(singer_name, "q\\n") || !strcmp(singer_name, "Q\\n")) {
break;
}
// 서버로부터 응답받기
str_len = read(sock, message, BUF_SIZE - 1);
if (str_len == -1)
error_handling("read() error");
message[str_len] = 0; // 널 문자로 끝냄
printf("Server response: %s\\n", message);
// 서버가 새로운 노래 목록을 요청할 때
if (!strcmp(message, "Singer not found. Please provide songs for this singer:\\n")) {
printf("Input songs for new singer: ");
fgets(message, BUF_SIZE, stdin);
// 노래 목록 서버로 전송
write(sock, message, strlen(message));
// 서버로부터 추가 확인 메시지 읽기
str_len = read(sock, message, BUF_SIZE - 1);
message[str_len] = 0;
printf("Server response: %s\\n", message);
}
}
close(sock);
return 0;
}
void error_handling(char *message) {
fputs(message, stderr);
fputc('\\n', stderr);
exit(1);
}
이 프로젝트는 C언어와 TCP 소켓 프로그래밍을 활용하여 서버와 클라이언트 간의 데이터 통신을 구현한 애플리케이션입니다. 클라이언트는 가수의 이름을 입력하면, 서버는 해당 가수의 노래 목록을 반환합니다. 사용자가 서버에 등록되지 않은 가수 이름을 입력하면, 새로운 가수와 노래 목록을 서버에 추가할 수 있는 기능도 제공합니다. 이를 통해 간단한 데이터베이스 기능을 포함한 서버-클라이언트 통신을 구현하였습니다.
가수와 노래 검색 기능:
클라이언트는 가수 이름을 입력하여 해당 가수의 노래 목록을 서버로부터 받을 수 있습니다. 서버는 미리 정의된 가수들과 그들의 노래 목록을 저장하고 있으며, 클라이언트로부터 요청이 들어올 때 이를 확인하고 결과를 전송합니다.
가수 및 노래 목록 추가 기능:
서버에 등록되지 않은 가수의 이름을 클라이언트가 입력하면, 서버는 해당 가수를 찾지 못했다고 알립니다. 이때 클라이언트는 해당 가수의 노래 목록을 입력하여 서버에 새로운 가수 데이터를 추가할 수 있습니다. 이를 통해 서버는 지속적으로 새로운 데이터를 저장하게 됩니다.
TCP 소켓 통신:
이 프로젝트는 TCP 소켓을 활용하여 클라이언트와 서버 간의 신뢰성 있는 데이터 전송을 구현하였습니다. 클라이언트는 소켓을 통해 서버에 연결되고, 가수 이름을 서버로 전송한 후, 서버로부터 응답을 받는 방식으로 동작합니다. 서버는 여러 클라이언트의 요청을 처리할 수 있는 구조로 설계되었습니다.
데이터 유효성 검사 및 종료:
클라이언트는 'q' 또는 'Q'를 입력하여 서버와의 연결을 종료할 수 있으며, 서버는 유효하지 않은 요청이나 입력에 대해 적절한 메시지를 반환합니다.
이 프로젝트는 TCP/IP 네트워크 통신에 대한 이해를 바탕으로, 서버와 클라이언트가 어떻게 데이터를 주고받는지에 대한 학습을 목적으로 시작되었습니다. 단순한 메시지 교환이 아닌, 서버에 데이터를 추가하고 저장하는 기능을 구현함으로써 소켓 프로그래밍에 대한 심화된 이해를 목표로 했습니다. 또한, 이를 통해 C언어의 기본 입출력과 메모리 관리에 대한 이해를 더 깊이 하게 되었습니다.