호타리
2025. 5. 29. 18:38
2025.05.29
sercer.c
// server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 9000
static void kill_port_users(int port) {
char cmd[64];
snprintf(cmd, sizeof(cmd), "fuser -k %d/tcp 2>/dev/null", port);
system(cmd);
}
int main(void) {
int server_sock, client_sock;
struct sockaddr_in saddr, caddr;
socklen_t addr_len = sizeof(caddr);
char buf[1024];
ssize_t r;
int opt = 1;
// 기존 포트 점유 프로세스 제거
kill_port_users(PORT);
// 1) socket()
if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 1;
}
// 2) SO_REUSEADDR
if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
perror("setsockopt");
close(server_sock);
return 1;
}
// 3) bind()
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(PORT);
if (bind(server_sock, (struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
perror("bind");
close(server_sock);
return 1;
}
// 4) listen()
if (listen(server_sock, 2) < 0) {
perror("listen");
close(server_sock);
return 1;
}
printf("▶ Server listening on port %d …\n", PORT);
// 5) accept()
if ((client_sock = accept(server_sock, (struct sockaddr*)&caddr, &addr_len)) < 0) {
perror("accept");
close(server_sock);
return 1;
}
// 6) 원격 엔드포인트 정보 출력
printf("▶ Client connected!\n");
printf(" RemoteEP_ADDR = %s\n", inet_ntoa(caddr.sin_addr));
printf(" RemoteEP_port = %d\n", ntohs(caddr.sin_port));
// 7) read loop
while ((r = read(client_sock, buf, sizeof(buf)-1)) > 0) {
buf[r] = '\0';
printf("> %s (%zd bytes)\n", buf, r);
}
if (r < 0) perror("read");
close(client_sock);
close(server_sock);
return 0;
}
client.c
// client.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 9000
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in saddr;
char buf[500];
ssize_t w;
if (argc != 2) {
fprintf(stderr, "Usage: %s <server_ip>\n", argv[0]);
return 1;
}
const char *server_ip = argv[1];
// 1) 소켓 생성
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 1;
}
// 2) 서버 주소 세팅
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PORT);
if (inet_aton(server_ip, &saddr.sin_addr) == 0) {
fprintf(stderr, "Invalid IP address: %s\n", server_ip);
close(sock);
return 1;
}
// 3) 서버에 연결
if (connect(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
perror("connect");
close(sock);
return 1;
}
// 4) 연결 정보 출력
printf("▶ Connected to %s:%d\n", server_ip, PORT);
printf(" Server_ADDR = %s\n", inet_ntoa(saddr.sin_addr));
printf(" Server_PORT = %d\n", ntohs(saddr.sin_port));
// 5) stdin에서 한 줄씩 읽어서 서버로 전송 (“> ” 프롬프트 추가)
while (1) {
printf("> "); // 프롬프트
fflush(stdout); // 바로 출력되도록 플러시
if (!fgets(buf, sizeof(buf), stdin))
break; // EOF 또는 에러 시 종료
size_t len = strlen(buf);
if (len > 0 && buf[len-1] == '\n')
buf[len-1] = '\0'; // 개행 제거
if (buf[0] == '\0')
continue; // 빈 줄은 건너뛰기
w = write(sock, buf, strlen(buf));
if (w < 0) {
perror("write");
break;
}
}
close(sock);
return 0;
}