C
[리눅스] 파이프를 사용한 단체방 채팅 서버 만들기(2)
돌맹96
2023. 12. 6. 22:44
728x90
반응형
앞서 만든 프로젝트에서 [C] 파이프를 사용한 단체방 채팅 서버 만들기 (tistory.com)
[C] 파이프를 사용한 단체방 채팅 서버 만들기
서버는 클라이언트 접속용 server pipe file을 생성하고 기다린다. 클라이언트는 server pipe file을 사용하여 클라이언트 접속을 서버에게 알린다. 이때 클라이언트가 생성한 client pipe file 이름을 포함
sdm6410.tistory.com
기능을 좀 추가해볼 생각이다.
추가기능 : 본인의 채팅은 받지 못하고 client_id를 추가한다. 코드는 다음과 같다.
서버
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define SERVER_PIPE "/tmp/server_pipe"
#define CLIENT_PIPE "/tmp/client_%d_pipe"
typedef struct {
char name[100]; // 클라이언트의 이름 또는 식별자
int fd; // 파일 디스크립터
} Client;
Client clients[10];
int client_count = 0;
// 메시지를 모든 클라이언트에게 전송 (발신자 제외)
void broadcast_message(const char *message, const char *sender_id) {
for (int i = 0; i < client_count; i++) {
if (strcmp(clients[i].name, sender_id) != 0) {
write(clients[i].fd, message, strlen(message) + 1);
}
}
}
int main() {
mkfifo(SERVER_PIPE, 0666);
int server_fd = open(SERVER_PIPE, O_RDONLY);
char buffer[300], sender_id[100];
while (1) {
read(server_fd, buffer, sizeof(buffer));
if (strncmp("CONNECT", buffer, 7) == 0) {
char client_pipe[100];
sscanf(buffer, "CONNECT %s", client_pipe);
int client_fd = open(client_pipe, O_WRONLY);
Client new_client;
strcpy(new_client.name, client_pipe); // 클라이언트 식별자 설정
new_client.fd = client_fd;
clients[client_count++] = new_client;
printf("New client connected: %s\n", new_client.name);
} else {
// 발신자 식별자와 메시지를 분리
sscanf(buffer, "%s %[^\n]", sender_id, buffer);
printf("Received message from %s: %s\n", sender_id, buffer);
broadcast_message(buffer, sender_id);
}
}
close(server_fd);
unlink(SERVER_PIPE);
return 0;
}
클라이언트
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define SERVER_PIPE "/tmp/server_pipe"
#define CLIENT_PIPE "/tmp/client_%d_pipe"
int main() {
int pid = getpid();
char client_pipe[100];
sprintf(client_pipe, CLIENT_PIPE, pid);
mkfifo(client_pipe, 0666);
int server_fd = open(SERVER_PIPE, O_WRONLY);
char buffer[300], message[256];
// 클라이언트 식별자 설정 (예: 프로세스 ID를 사용)
char client_id[100];
sprintf(client_id, "client_%d", pid);
// 서버에 연결 요청 메시지 전송
sprintf(buffer, "CONNECT %s", client_pipe);
write(server_fd, buffer, strlen(buffer) + 1);
pid_t child_pid = fork();
if (child_pid == 0) { // 자식 프로세스: 서버로부터 메시지 수신
int client_fd = open(client_pipe, O_RDONLY);
while (1) {
ssize_t count = read(client_fd, message, sizeof(message));
if (count <= 0) {
printf("Connection lost. Exiting.\n");
break;
}
printf("Received message: %s\n", message);
}
close(client_fd);
exit(0);
} else { // 부모 프로세스: 사용자 입력을 서버로 전송
while (1) {
fgets(message, sizeof(message), stdin);
sprintf(buffer, "%s: %s", client_id, message);
write(server_fd, buffer, strlen(buffer) + 1);
}
}
close(server_fd);
unlink(client_pipe);
return 0;
}
728x90
반응형