작업 설명
Huawei Kunpeng 클라우드 서버의 CentOS 또는 Ubuntu 환경에서 Linux Socket을 사용하여 다음을 구현합니다:
- time 서버의 클라이언트와 서버를 작성하고, 실행 화면을 제출하세요.
- echo 서버의 클라이언트와 서버를 작성하고, 실행 화면을 제출하세요. 서버는 클라이언트로부터 받은 내용에 "서버 PID 학번 이름 echo:"를 추가하여 반환합니다.
- 서버를 Huawei 클라우드 서버에 배포하고, 클라이언트는 Ubuntu 가상 머신을 사용합니다.
- 멀티스레드 또는 멀티프로세스를 사용하여 최소 두 개의 클라이언트 연결을 지원해야 합니다.
- 서버를 실험 상자에 배포합니다 (가산점 항목).
코드:
클라이언트 코드:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#define BUFFER_SIZE 1024
#define ERR_CODE -1
void *send_thread(void *arg) {
char buffer[BUFFER_SIZE];
int sock = *(int *)arg;
while (1) {
memset(buffer, 0, sizeof(buffer));
read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
if (send(sock, buffer, strlen(buffer), 0) == -1) {
perror("send error");
break;
}
}
return NULL;
}
void *recv_thread(void *arg) {
char buffer[BUFFER_SIZE];
int sock = *(int *)arg;
while (1) {
memset(buffer, 0, sizeof(buffer));
int recv_len = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (recv_len <= 0) {
if (recv_len == 0) {
printf("Server closed\n");
exit(0);
}
perror("recv error");
break;
}
printf("\nReceived from server:\n%s", buffer);
}
return NULL;
}
int start_client(char *ip_addr, int port) {
int client_sock;
struct sockaddr_in server_addr;
client_sock = socket(AF_INET, SOCK_STREAM, 0);
if (client_sock == -1) {
perror("socket creation error");
return ERR_CODE;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(ip_addr);
if (connect(client_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connection error");
return ERR_CODE;
}
pthread_t send_tid, recv_tid;
if (pthread_create(&send_tid, NULL, send_thread, &client_sock) != 0) {
perror("thread creation error");
return ERR_CODE;
}
if (pthread_create(&recv_tid, NULL, recv_thread, &client_sock) != 0) {
perror("thread creation error");
return ERR_CODE;
}
pthread_join(recv_tid, NULL);
pthread_join(send_tid, NULL);
close(client_sock);
return 0;
}
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: %s IP PORT\n", argv[0]);
return ERR_CODE;
}
int port = atoi(argv[2]);
char *ip_addr = argv[1];
start_client(ip_addr, port);
return 0;
}
서버 코드:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#define BUFFER_SIZE 1024
#define ERR_CODE -1
void *handle_client(void *arg) {
int client_sock = *(int *)arg;
char buffer[BUFFER_SIZE];
pid_t pid = getpid();
char msg_prefix[64];
sprintf(msg_prefix, "PID %d 학번 이름 echo: ", pid);
while (1) {
memset(buffer, 0, BUFFER_SIZE);
int recv_len = recv(client_sock, buffer, BUFFER_SIZE - 1, 0);
if (recv_len <= 0) {
if (recv_len == 0) {
printf("Client disconnected\n");
break;
}
perror("recv error");
break;
}
strcat(msg_prefix, buffer);
if (send(client_sock, msg_prefix, strlen(msg_prefix), 0) == -1) {
perror("send error");
break;
}
memset(msg_prefix, 0, sizeof(msg_prefix));
sprintf(msg_prefix, "PID %d 학번 이름 echo: ", pid);
}
close(client_sock);
return NULL;
}
int start_server(int port) {
int server_sock, client_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);
server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock == -1) {
perror("socket creation error");
return ERR_CODE;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind error");
return ERR_CODE;
}
if (listen(server_sock, 5) == -1) {
perror("listen error");
return ERR_CODE;
}
while (1) {
client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &addr_len);
if (client_sock == -1) {
perror("accept error");
continue;
}
pthread_t thread_id;
if (pthread_create(&thread_id, NULL, handle_client, &client_sock) != 0) {
perror("thread creation error");
close(client_sock);
}
}
close(server_sock);
return 0;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s PORT\n", argv[0]);
return ERR_CODE;
}
int port = atoi(argv[1]);
start_server(port);
return 0;
}
실행 결과:
두 개의 가상 머신을 사용하여 하나는 클라이언트로, 다른 하나는 서버로 작동시킵니다.
서버는 동시에 여러 클라이언트로부터 메시지를 수신할 수 있습니다.