Skip to content
Snippets Groups Projects
Commit c708c546 authored by 천 진강's avatar 천 진강
Browse files

feat(c): Robust 환경 구축

parent d3c1f9c9
No related branches found
No related tags found
No related merge requests found
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <pthread.h> #include <pthread.h>
#include <signal.h>
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
#define PORT 12345 #define PORT 12345
...@@ -18,23 +19,35 @@ ...@@ -18,23 +19,35 @@
#define PTHREAD_STACK_MIN 16384 #define PTHREAD_STACK_MIN 16384
#endif #endif
typedef struct { typedef struct
{
int socket; int socket;
int used;
struct sockaddr_in address; struct sockaddr_in address;
} ClientData; } ClientData;
int pySocket, cSocket, clientCnt = 0; int pySocket, cSocket, clientCnt = 0, isAlive = 0;
pthread_t pyThread, clientThreads[MAX_CLIENTS]; pthread_t pyThread, clientThreads[MAX_CLIENTS];
ClientData clients[MAX_CLIENTS]; ClientData clients[MAX_CLIENTS];
struct sockaddr_in pyAddr, cAddr, clientAddr;
pthread_attr_t attr, attr2, at[3];
struct sched_param param, param2;
void *ClientToServer(void *idx); // 클라이언트 => 서버 메세지 전달
void *ServerToClient(); // 서버 => 클라이언트 메세지 전달
void handleForce(int signal); // 강제 종료시 리소스 반환
static int PWMExport(int pwmnum) { static int PWMExport(int pwmnum)
{
#define BUFFER_MAX 3 #define BUFFER_MAX 3
char buffer[BUFFER_MAX]; char buffer[BUFFER_MAX];
int fd, byte; int fd, byte;
// TODO: Enter the export path. // TODO: Enter the export path.
fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY); fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY);
if (-1 == fd) { if (-1 == fd)
{
fprintf(stderr, "Failed to open export for export!\n"); fprintf(stderr, "Failed to open export for export!\n");
return (-1); return (-1);
} }
...@@ -48,14 +61,16 @@ static int PWMExport(int pwmnum) { ...@@ -48,14 +61,16 @@ static int PWMExport(int pwmnum) {
return (0); return (0);
} }
static int PWMUnexport(int pwmnum) { static int PWMUnexport(int pwmnum)
{
#define BUFFER_MAX 3 #define BUFFER_MAX 3
char buffer[BUFFER_MAX]; char buffer[BUFFER_MAX];
int fd, byte; int fd, byte;
// TODO: Enter the export path. // TODO: Enter the export path.
fd = open("/sys/class/pwm/pwmchip0/unexport", O_WRONLY); fd = open("/sys/class/pwm/pwmchip0/unexport", O_WRONLY);
if (-1 == fd) { if (-1 == fd)
{
fprintf(stderr, "Failed to open export for unexport!\n"); fprintf(stderr, "Failed to open export for unexport!\n");
return (-1); return (-1);
} }
...@@ -69,7 +84,8 @@ static int PWMUnexport(int pwmnum) { ...@@ -69,7 +84,8 @@ static int PWMUnexport(int pwmnum) {
return (0); return (0);
} }
static int PWMEnable(int pwmnum) { static int PWMEnable(int pwmnum)
{
static const char s_enable_str[] = "1"; static const char s_enable_str[] = "1";
char path[DIRECTION_MAX]; char path[DIRECTION_MAX];
...@@ -78,7 +94,8 @@ static int PWMEnable(int pwmnum) { ...@@ -78,7 +94,8 @@ static int PWMEnable(int pwmnum) {
// TODO: Enter the enable path. // TODO: Enter the enable path.
snprintf(path, DIRECTION_MAX, "/sys/class/pwm/pwmchip0/pwm0/enable"); snprintf(path, DIRECTION_MAX, "/sys/class/pwm/pwmchip0/pwm0/enable");
fd = open(path, O_WRONLY); fd = open(path, O_WRONLY);
if (-1 == fd) { if (-1 == fd)
{
fprintf(stderr, "Failed to open in enable!\n"); fprintf(stderr, "Failed to open in enable!\n");
return -1; return -1;
} }
...@@ -88,7 +105,8 @@ static int PWMEnable(int pwmnum) { ...@@ -88,7 +105,8 @@ static int PWMEnable(int pwmnum) {
return (0); return (0);
} }
static int PWMWritePeriod(int pwmnum, int value) { static int PWMWritePeriod(int pwmnum, int value)
{
char s_value_str[VALUE_MAX]; char s_value_str[VALUE_MAX];
char path[VALUE_MAX]; char path[VALUE_MAX];
int fd, byte; int fd, byte;
...@@ -96,13 +114,15 @@ static int PWMWritePeriod(int pwmnum, int value) { ...@@ -96,13 +114,15 @@ static int PWMWritePeriod(int pwmnum, int value) {
// TODO: Enter the period path. // TODO: Enter the period path.
snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm0/period"); snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm0/period");
fd = open(path, O_WRONLY); fd = open(path, O_WRONLY);
if (-1 == fd) { if (-1 == fd)
{
fprintf(stderr, "Failed to open in period!\n"); fprintf(stderr, "Failed to open in period!\n");
return (-1); return (-1);
} }
byte = snprintf(s_value_str, VALUE_MAX, "%d", value); byte = snprintf(s_value_str, VALUE_MAX, "%d", value);
if (-1 == write(fd, s_value_str, byte)) { if (-1 == write(fd, s_value_str, byte))
{
fprintf(stderr, "Failed to write value in period!\n"); fprintf(stderr, "Failed to write value in period!\n");
close(fd); close(fd);
return -1; return -1;
...@@ -112,7 +132,8 @@ static int PWMWritePeriod(int pwmnum, int value) { ...@@ -112,7 +132,8 @@ static int PWMWritePeriod(int pwmnum, int value) {
return (0); return (0);
} }
static int PWMWriteDutyCycle(int pwmnum, int value) { static int PWMWriteDutyCycle(int pwmnum, int value)
{
char s_value_str[VALUE_MAX]; char s_value_str[VALUE_MAX];
char path[VALUE_MAX]; char path[VALUE_MAX];
int fd, byte; int fd, byte;
...@@ -120,13 +141,15 @@ static int PWMWriteDutyCycle(int pwmnum, int value) { ...@@ -120,13 +141,15 @@ static int PWMWriteDutyCycle(int pwmnum, int value) {
// TODO: Enter the duty_cycle path. // TODO: Enter the duty_cycle path.
snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm0/duty_cycle"); snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm0/duty_cycle");
fd = open(path, O_WRONLY); fd = open(path, O_WRONLY);
if (-1 == fd) { if (-1 == fd)
{
fprintf(stderr, "Failed to open in duty cycle!\n"); fprintf(stderr, "Failed to open in duty cycle!\n");
return (-1); return (-1);
} }
byte = snprintf(s_value_str, VALUE_MAX, "%d", value); byte = snprintf(s_value_str, VALUE_MAX, "%d", value);
if (-1 == write(fd, s_value_str, byte)) { if (-1 == write(fd, s_value_str, byte))
{
fprintf(stderr, "Failed to write value in duty cycle!\n"); fprintf(stderr, "Failed to write value in duty cycle!\n");
close(fd); close(fd);
return -1; return -1;
...@@ -136,120 +159,35 @@ static int PWMWriteDutyCycle(int pwmnum, int value) { ...@@ -136,120 +159,35 @@ static int PWMWriteDutyCycle(int pwmnum, int value) {
return (0); return (0);
} }
// 클라이언트 수신 스레드 함수 int main()
void *ClientToServer(void *idx) { {
int i = *((int*) idx); socklen_t clientAddrLen = sizeof(clientAddr);
char buffer[BUFFER_SIZE];
char ip[INET_ADDRSTRLEN];
int len;
while ((len = recv(clients[i].socket, buffer, BUFFER_SIZE, 0)) > 0) {
buffer[len] = '\0';
inet_ntop(AF_INET, &clients[i].address.sin_addr, ip, INET_ADDRSTRLEN);
printf("Received from client %s: %s", ip, buffer);
if (send(pySocket, buffer, strlen(buffer), 0) < 0) {
perror("Send message to server error");
}
}
if (len == 0) {
printf("Client disconnected: %d\n", clients[i].socket);
} else if (len == -1) {
perror("recv error");
}
clientCnt--;
close(clients[i].socket);
}
// 서버에서 메시지 수신하는 스레드
void *ServerToClient() {
char buffer[BUFFER_SIZE];
int len;
while (1) {
if (len = recv(pySocket, buffer, BUFFER_SIZE - 1, 0) <= 0) {
printf("Server disconnected\n");
close(pySocket);
exit(0);
}
buffer[len] = '\0';
printf("Received from server: %s\n", buffer);
if (buffer[2] == 'Y') {
// 차단기 개방
printf("차단기 개방\n");
if (PWMExport(PWM)) printf("export error\n");
if (PWMWritePeriod(PWM, 20000000)) printf("period error\n");
if (PWMWriteDutyCycle(PWM, 0)) printf("duty error\n");
if (PWMEnable(PWM)) printf("enable error\n");
if (PWMWriteDutyCycle(PWM, 2000000)) printf("duty error2\n");
usleep(100000);
if (PWMUnexport(PWM)) printf("unexport error\n");
}
else if (buffer[2] == 'P') {
// 충전기 노드에 주차 사실 알림
if (send(clients[0].socket, buffer, strlen(buffer), 0) < 0) {
perror("Send message error");
}
if (send(clients[1].socket, buffer, strlen(buffer), 0) < 0) {
perror("Send message error");
}
}
else if (buffer[2] == 'E') {
if (send(clients[0].socket, buffer, strlen(buffer), 0) < 0) {
perror("Send message error");
}
if (send(clients[1].socket, buffer, strlen(buffer), 0) < 0) {
perror("Send message error");
}
if (PWMExport(PWM)) printf("export error\n");
if (PWMWritePeriod(PWM, 20000000)) printf("period error\n");
if (PWMWriteDutyCycle(PWM, 0)) printf("duty error\n");
if (PWMEnable(PWM)) printf("enable error\n");
if (PWMWriteDutyCycle(PWM, 950000)) printf("duty error2\n");
usleep(100000);
if (PWMUnexport(PWM)) printf("unexport error\n");
}
else if (buffer[2] == 'F') {
// 충전기 노드에 화재 사실 알림
// 화재 노드에 화재 사실 알림
if (send(clients[0].socket, buffer, strlen(buffer), 0) < 0) {
perror("Send message error");
}
if (send(clients[2].socket, buffer, strlen(buffer), 0) < 0) { // 강제 종료시 리소스 반환
perror("Send message error"); signal(SIGINT, handleForce);
} signal(SIGTERM, handleForce);
} signal(SIGSEGV, handleForce);
signal(SIGKILL, handleForce);
else if (buffer[0] == 'C') { // clients 배열 초기화
for (int x = 0; x < 3; x++) { for (int i = 0; i < MAX_CLIENTS; i++)
if (send(clients[x].socket, buffer, strlen(buffer), 0) < 0) { {
perror("Send message error"); memset(clients, 0, sizeof(clients));
}
}
}
}
} }
int main() { // 스케쥴링 우선순위 설정
struct sockaddr_in pyAddr, cAddr, clientAddr;
pthread_attr_t attr, attr2, at[3];
struct sched_param param, param2;
socklen_t clientAddrLen = sizeof(clientAddr);
param.sched_priority = sched_get_priority_max(SCHED_RR); param.sched_priority = sched_get_priority_max(SCHED_RR);
param2.sched_priority = sched_get_priority_max(SCHED_RR) - 1; param2.sched_priority = sched_get_priority_max(SCHED_RR) - 1;
// 스레드 속성 부여
pthread_attr_init(&at[2]); pthread_attr_init(&at[2]);
pthread_attr_setschedpolicy(&at[2], SCHED_RR); pthread_attr_setschedpolicy(&at[2], SCHED_RR);
pthread_attr_setinheritsched(&at[2], PTHREAD_EXPLICIT_SCHED); pthread_attr_setinheritsched(&at[2], PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedparam(&at[2], &param); pthread_attr_setschedparam(&at[2], &param);
pthread_attr_setstacksize(&at[2], PTHREAD_STACK_MIN); pthread_attr_setstacksize(&at[2], PTHREAD_STACK_MIN);
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++)
{
pthread_attr_init(&at[i]); pthread_attr_init(&at[i]);
pthread_attr_setschedpolicy(&at[i], SCHED_RR); pthread_attr_setschedpolicy(&at[i], SCHED_RR);
pthread_attr_setinheritsched(&at[i], PTHREAD_EXPLICIT_SCHED); pthread_attr_setinheritsched(&at[i], PTHREAD_EXPLICIT_SCHED);
...@@ -258,82 +196,277 @@ int main() { ...@@ -258,82 +196,277 @@ int main() {
} }
// 서버로 연결할 클라이언트 소켓 생성 // 서버로 연결할 클라이언트 소켓 생성
if ((pySocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { if ((pySocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("Socket creation error"); {
fprintf(stderr, "Socket creation error\n");
return -1; return -1;
} }
// 서버로 메시지 전송할 소켓 설정 // 서버로 메시지 전송할 소켓 설정
pyAddr.sin_family = AF_INET; pyAddr.sin_family = AF_INET;
pyAddr.sin_port = htons(49152); pyAddr.sin_port = htons(49152);
if (inet_pton(AF_INET, "127.0.0.1", &pyAddr.sin_addr) <= 0) { if (inet_pton(AF_INET, "127.0.0.1", &pyAddr.sin_addr) <= 0)
perror("Address error"); {
fprintf(stderr, "Address error\n");
close(pySocket);
return -1; return -1;
} }
if (connect(pySocket, (struct sockaddr *)&pyAddr, sizeof(pyAddr)) < 0) {
perror("Connection error"); // 서버 연결
if (connect(pySocket, (struct sockaddr *)&pyAddr, sizeof(pyAddr)) < 0)
{
fprintf(stderr, "Connection error\n");
close(pySocket);
return -1; return -1;
} }
printf("Connected to server\n"); printf("Connected to server\n");
isAlive = 1;
// 서버 통신 스레드 생성
pthread_create(&pyThread, &at[2], ServerToClient, NULL);
if (pthread_detach(pyThread) < 0)
{
fprintf(stderr, "Detach thread error\n");
close(pySocket);
return -1;
}
// 클라이언트를 받을 서버 소켓 설정 // 클라이언트를 받을 서버 소켓 설정
if ((cSocket = socket(AF_INET, SOCK_STREAM, 0)) == 0) { if ((cSocket = socket(AF_INET, SOCK_STREAM, 0)) == 0)
perror("Socket error"); {
fprintf(stderr, "Socket error\n");
close(pySocket);
close(cSocket);
return -1; return -1;
} }
cAddr.sin_family = AF_INET; cAddr.sin_family = AF_INET;
cAddr.sin_addr.s_addr = INADDR_ANY; cAddr.sin_addr.s_addr = INADDR_ANY;
cAddr.sin_port = htons(PORT); cAddr.sin_port = htons(PORT);
if (bind(cSocket, (struct sockaddr *)&cAddr, sizeof(cAddr)) < 0) { if (bind(cSocket, (struct sockaddr *)&cAddr, sizeof(cAddr)) < 0)
perror("Bind error"); {
fprintf(stderr, "Bind error\n");
close(cSocket); close(cSocket);
close(pySocket);
return -1; return -1;
} }
if (listen(cSocket, 3) < 0) { if (listen(cSocket, 3) < 0)
perror("Listen error"); {
fprintf(stderr, "Listen error\n");
close(cSocket); close(cSocket);
close(pySocket);
return -1; return -1;
} }
// 서버 수신용 스레드 시작 // 클라이언트 처리 로직
pthread_create(&pyThread, NULL, ServerToClient, NULL); while (clientCnt < MAX_CLIENTS)
{
while (clientCnt < MAX_CLIENTS) {
int x; int x;
char ip[INET_ADDRSTRLEN]; char ip[INET_ADDRSTRLEN];
if ((x = accept(cSocket, (struct sockaddr *)&clientAddr, &clientAddrLen)) < 0) { if ((x = accept(cSocket, (struct sockaddr *)&clientAddr, &clientAddrLen)) < 0)
perror("Accept error"); {
fprintf(stderr, "Accept error\n");
continue; continue;
} }
int *idx = (int *)malloc(sizeof(int *));
// *idx = ip[11] - '7';
// if (ip[11] - '7' > 2 || ip[11] - '7' < 0) *idx = 0;
*idx = clientCnt;
ClientData *tmp = (ClientData *)malloc(sizeof(ClientData)); ClientData *tmp = (ClientData *)malloc(sizeof(ClientData));
tmp->socket = x; tmp->socket = x;
tmp->address = clientAddr; tmp->address = clientAddr;
clients[clientCnt] = *tmp; clients[*idx] = *tmp;
clients[*idx].used = 1;
inet_ntop(AF_INET, &tmp->address.sin_addr, ip, INET_ADDRSTRLEN); inet_ntop(AF_INET, &tmp->address.sin_addr, ip, INET_ADDRSTRLEN);
//int *idx = (int *)malloc(sizeof(int *));
int *idx = ip[11] - '7';
if (ip[11] - '7' > 2 || ip[11] - '7' < 0) *idx = 0;
*idx = clientCnt;
if (pthread_create(&clientThreads[*idx], &at[*idx], ClientToServer, (void *)idx) < 0) { if (pthread_create(&clientThreads[*idx], &at[*idx], ClientToServer, (void *)idx) < 0)
perror("Create thread error"); {
fprintf(stderr, "Create thread error\n");
close(x); close(x);
free(tmp); free(tmp);
} }
if (pthread_detach(clientThreads[*idx]) < 0) { if (pthread_detach(clientThreads[*idx]) < 0)
perror("Detach thread error"); {
fprintf(stderr, "Detach thread error\n");
close(x); close(x);
free(tmp); free(tmp);
} }
clientCnt++;
} }
close(pySocket); close(pySocket);
close(cSocket); close(cSocket);
return 0; return 0;
} }
void *ClientToServer(void *idx)
{
int i = *((int *)idx);
char buffer[BUFFER_SIZE];
char ip[INET_ADDRSTRLEN];
int len;
while ((len = recv(clients[i].socket, buffer, BUFFER_SIZE, 0)) > 0)
{
buffer[len] = '\0';
inet_ntop(AF_INET, &clients[i].address.sin_addr, ip, INET_ADDRSTRLEN);
printf("Received from client %s: %s", ip, buffer);
if (isAlive && send(pySocket, buffer, strlen(buffer), 0) < 0)
{
fprintf(stderr, "Send message to server error\n");
}
}
if (len == 0)
{
printf("Client disconnected: %d\n", clients[i].socket);
}
else if (len == -1)
{
fprintf(stderr, "recv error\n");
}
clientCnt--;
close(clients[i].socket);
}
void *ServerToClient()
{
char buffer[BUFFER_SIZE];
int len;
while (1)
{
if ((len = recv(pySocket, buffer, BUFFER_SIZE - 1, 0)) <= 0)
{
printf("Server disconnected\n");
isAlive = 0;
close(pySocket);
usleep(2500000);
if ((pySocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "Socket creation error\n");
continue;
}
// 서버로 메시지 전송할 소켓 설정
pyAddr.sin_family = AF_INET;
pyAddr.sin_port = htons(49152);
if (inet_pton(AF_INET, "127.0.0.1", &pyAddr.sin_addr) <= 0)
{
fprintf(stderr, "Address error\n");
close(pySocket);
continue;
}
if (connect(pySocket, (struct sockaddr *)&pyAddr, sizeof(pyAddr)) < 0)
{
fprintf(stderr, "Connection error\n");
close(pySocket);
continue;
}
isAlive = 1;
printf("Connected to server\n");
memset(buffer, 0, sizeof(buffer));
}
buffer[len] = '\0';
printf("Received from server: %s\n", buffer);
if (buffer[2] == 'Y')
{
// 차단기 개방
printf("차단기 개방\n");
if (PWMExport(PWM))
fprintf(stderr, "export error\n");
if (PWMWritePeriod(PWM, 20000000))
fprintf(stderr, "period error\n");
if (PWMWriteDutyCycle(PWM, 0))
fprintf(stderr, "duty error\n");
if (PWMEnable(PWM))
fprintf(stderr, "enable error\n");
if (PWMWriteDutyCycle(PWM, 2000000))
fprintf(stderr, "duty error2\n");
usleep(100000);
if (PWMUnexport(PWM))
fprintf(stderr, "unexport error\n");
}
else if (buffer[2] == 'P')
{
// 충전기 노드에 주차 사실 알림
if (clients[0].used != 0 && send(clients[0].socket, buffer, strlen(buffer), 0) < 0)
{
fprintf(stderr, "Send message error\n");
}
if (clients[1].used != 0 && send(clients[1].socket, buffer, strlen(buffer), 0) < 0)
{
fprintf(stderr, "Send message error\n");
}
}
else if (buffer[2] == 'E')
{
if (clients[0].used != 0 && send(clients[0].socket, buffer, strlen(buffer), 0) < 0)
{
fprintf(stderr, "Send message error\n");
}
if (clients[1].used != 0 && send(clients[1].socket, buffer, strlen(buffer), 0) < 0)
{
fprintf(stderr, "Send message error\n");
}
if (PWMExport(PWM))
fprintf(stderr, "export error\n");
if (PWMWritePeriod(PWM, 20000000))
fprintf(stderr, "period error\n");
if (PWMWriteDutyCycle(PWM, 0))
fprintf(stderr, "duty error\n");
if (PWMEnable(PWM))
fprintf(stderr, "enable error\n");
if (PWMWriteDutyCycle(PWM, 950000))
fprintf(stderr, "duty error2\n");
usleep(100000);
if (PWMUnexport(PWM))
fprintf(stderr, "unexport error\n");
}
else if (buffer[2] == 'F')
{
// 충전기 노드에 화재 사실 알림
// 화재 노드에 화재 사실 알림
if (clients[0].used != 0 && send(clients[0].socket, buffer, strlen(buffer), 0) < 0)
{
fprintf(stderr, "Send message error\n");
}
if (clients[2].used != 0 && send(clients[2].socket, buffer, strlen(buffer), 0) < 0)
{
fprintf(stderr, "Send message error\n");
}
}
else if (buffer[0] == 'C')
{
for (int x = 0; x < 3; x++)
{
if (clients[x].used != 0 && send(clients[x].socket, buffer, strlen(buffer), 0) < 0)
{
fprintf(stderr, "Send message error\n");
}
}
}
}
}
void handleForce(int signal)
{
shutdown(pySocket, SHUT_RDWR);
close(pySocket);
close(cSocket);
pthread_cancel(pyThread);
printf("%d stop\n", signal);
exit(0);
}
package org.example.thiefsil.dto;
public class FireDTO {
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment