반응형
요즘 c언어가 별로 없다 보니 생각보다 자료나 연동에 있어서 고생을 많이 한다...
이번에 프로젝트에서 아두이노 라즈베리파이 plc.. 등등 연동하다가 https 웹소켓을 함께 연동하는 일이 생겨서
겸사겸사 올려본다.
/*==============================================================================================/
*
* Copyright (C) 2021 Qsentech Software Corp Reaserch Institute
* All rights reserved.
*
* Author : Lee Kyu Nam (nasanx2001@naver.com)
*
*==============================================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <curl/curl.h>
#include <time.h>
#include <unistd.h>
#include <sys/shm.h>
#include "cJSON.h"
#undef FALSE
#define FALSE 0
#undef TRUE
#define TRUE 1
#ifdef _WIN32
#undef snprintf
#define snprintf _snprintf
#endif
#define _status_item 28
typedef struct tm tm;
int old_min = 0;
struct _dev *dev_shm;
void *dev_shared_memory = (void *)0;
#define DEV_SHM_KEY 3131
struct _dev
{
char polling_data[2000];
int polling_flag;
char ack_data[2000];
int ack_flag;
};
struct _timer *timer_shm;
void *timer_shared_memory = (void *)0;
#define TIMER_SHM_KEY 2121
struct _timer
{
int yyyy;
int mm;
int md;
int hour;
int min;
int sec;
};
struct _set_Value *set_shm;
void *set_shared_memory = (void *)0;
#define SET_SHM_KEY 1111
struct _set_Value
{
int sensor1;
int sensor2;
int sensor3;
int sensor4;
int sensor5;
};
/* Post JSON data to a server.
name and value must be UTF-8 strings.
Returns TRUE on success, FALSE on failure.
*/
// test용
//========================================================================
char *key_name[] = {"systemDate", "systemId", "sensor1", "sensor2", "sensor3", "sensor4", "sensor5"};
struct MemoryStruct
{
char *memory;
size_t size;
};
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size = nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if(mem->memory == NULL)
{
printf("memory error\n");
return 0;
}
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
int PostJSON(int item)
{
int retcode = FALSE;
cJSON *root = NULL;
char *json = NULL;
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
char errbuf[CURL_ERROR_SIZE] = { 0, };
struct curl_slist *headers = NULL;
char agent[1024] = { 0, };
int i = 0;
char timer[18];
char *p;
char buff[400];
long statLong ;
FILE *fp;
fp = fopen("/home/ubuntu/log/post.txt", "a+");
sprintf(timer, "%04d%02d%02d %02d:%02d:%02d", timer_shm->yyyy, timer_shm->mm, timer_shm->md, timer_shm->hour, timer_shm->min, timer_shm->sec);
printf("%s\n", timer);
root = cJSON_CreateObject();
if(!root) {
fprintf(fp, "[%04d-%02d-%02d %02d:%02d:%02d] Error: cJSON_CreateObject failed.\n", timer_shm->yyyy, timer_shm->mm, timer_shm->md, timer_shm->hour,timer_shm->min, timer_shm->sec);
goto cleanup;
}
cJSON_AddStringToObject(root, key_name[i++], timer);
memset(buff, 0x00, sizeof(buff));
memcpy(buff, dev_shm->polling_data, strlen(dev_shm->polling_data));
p = strtok(buff, ", ");
while(p != NULL)
{
if(i < 7)
{
if((strcmp(p, "ex") != 0)) // ETX 테스트용
{
cJSON_AddStringToObject(root, key_name[i++], p);
}
}
p = strtok(NULL, ", ");
}
json = cJSON_PrintUnformatted(root);
if(!json) {
fprintf(fp, "[%04d-%02d-%02d %02d:%02d:%02d] Error: cJSON_PrintUnformatted failed.\n", timer_shm->yyyy, timer_shm->mm, timer_shm->md, timer_shm->hour,timer_shm->min, timer_shm->sec);
goto cleanup;
}
curl = curl_easy_init();
if(!curl) {
fprintf(fp, "[%04d-%02d-%02d %02d:%02d:%02d] Error: curl_easy_init failed.\n", timer_shm->yyyy, timer_shm->mm, timer_shm->md, timer_shm->hour,timer_shm->min, timer_shm->sec);
goto cleanup;
}
// debug
// printf("json = %s\n", json);
curl_easy_setopt(curl, CURLOPT_CAINFO, "tset.crt");
snprintf(agent, sizeof(agent), "libcurl/%s",
curl_version_info(CURLVERSION_NOW)->version);
agent[sizeof(agent) - 1] = 0;
curl_easy_setopt(curl, CURLOPT_USERAGENT, agent);
headers = curl_slist_append(headers, "Expect:");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);
/* This is a test server, it fakes a reply as if the json object were
created */
curl_easy_setopt(curl, CURLOPT_URL,
"https://xxx-xxxxxx/xxx.com/xx/xxxxxx");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
curl_easy_setopt (curl, CURLOPT_FORBID_REUSE, 1L);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
size_t len = strlen(errbuf);
fprintf(fp, "\nlibcurl: (%d)\n ", res);
if(len)
fprintf(fp, "[%04d-%02d-%02d %02d:%02d:%02d]%s%s\n", timer_shm->yyyy, timer_shm->mm, timer_shm->md, timer_shm->hour,timer_shm->min, timer_shm->sec, errbuf, ((errbuf[len - 1] != '\n') ? "\n" : ""));
fprintf(fp, "[%04d-%02d-%02d %02d:%02d:%02d]%s\n\n", timer_shm->yyyy, timer_shm->mm, timer_shm->md, timer_shm->hour,timer_shm->min, timer_shm->sec, curl_easy_strerror(res));
//goto cleanup;
}
else{
if( CURLE_OK == curl_easy_getinfo( curl , CURLINFO_HTTP_CODE , &statLong ) ){
// printf("[%04d-%02d-%02d %02d:%02d:%02d] RCV_HTTP_CODE : %ld\n", timer_shm->yyyy, timer_shm->mm, timer_shm->md, timer_shm->hour,
// timer_shm->min, timer_shm->sec, statLong);
fprintf(fp, "[%04d-%02d-%02d %02d:%02d:%02d] RCV_HTTP_CODE : %ld\n", timer_shm->yyyy, timer_shm->mm, timer_shm->md, timer_shm->hour,timer_shm->min, timer_shm->sec, statLong);
dev_shm->polling_flag = 0;
}
}
retcode = TRUE;
cleanup:
fclose(fp);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
cJSON_Delete(root);
free(json);
return retcode;
}
void timer_count()
{
time_t t = time(NULL);
struct tm tm = *localtime(&t);
timer_shm->yyyy = tm.tm_year+1900;
timer_shm->mm = tm.tm_mon+1;
timer_shm->md = tm.tm_mday;
timer_shm->hour = tm.tm_hour;
timer_shm->min = tm.tm_min;
timer_shm->sec = tm.tm_sec;
}
int main(int argc, char *argv[])
{
int dev_shmid;
int timer_shmid;
int set_shmid;
//=========================================================================================
dev_shmid = shmget((key_t)DEV_SHM_KEY, sizeof(char), 0666 | IPC_CREAT);
if(dev_shmid == -1)
{
perror("dev shmget fail");
exit(0);
}
dev_shared_memory = shmat(dev_shmid, (void *)0, 0);
if(dev_shared_memory == (void *)-1)
{
perror("dev shmat fail");
exit(0);
}
dev_shm = (struct _dev *)dev_shared_memory;
//=========================================================================================
//=========================================================================================
timer_shmid = shmget((key_t)TIMER_SHM_KEY, sizeof(char), 0666 | IPC_CREAT);
if(timer_shmid == -1)
{
perror("timer shmget fail");
exit(0);
}
timer_shared_memory = shmat(timer_shmid, (void *)0, 0);
if(timer_shared_memory == (void *)-1)
{
perror("timer shmat fail");
exit(0);
}
timer_shm = (struct _timer *)timer_shared_memory;
//=========================================================================================
//=========================================================================================
set_shmid = shmget((key_t)SET_SHM_KEY, sizeof(char), 0666 | IPC_CREAT);
if(set_shmid == -1)
{
perror("set shmget fail");
exit(0);
}
set_shared_memory = shmat(set_shmid, (void *)0, 0);
if(set_shared_memory == (void *)-1)
{
perror("set shmat fail");
exit(0);
}
set_shm = (struct _set_Value *)set_shared_memory;
//=========================================================================================
while(1)
{
sleep(1);
timer_count();
if(timer_shm->min != old_min)
{
old_min = timer_shm->min;
if(curl_global_init(CURL_GLOBAL_ALL)) {
fprintf(stderr, "Fatal: The initialization of libcurl has failed.\n");
return EXIT_FAILURE;
}
if(atexit(curl_global_cleanup)) {
fprintf(stderr, "Fatal: atexit failed to register curl_global_cleanup.\n");
curl_global_cleanup();
return EXIT_FAILURE;
}
if(dev_shm->polling_flag == 1)
{
if(!PostJSON(_status_item)) {
fprintf(stderr, "Fatal: PostJSON failed.\n");
return EXIT_FAILURE;
}
}
}
}
return EXIT_SUCCESS;
}
참고로 crt 인증서의 경우 해당 인증서 경로에 접속해야하는 서버의 인증서를 직접 받는 방법과
리눅스에서 해당 서버인증서를 확인하여 긁어오는 방법도 있다.
나 같은 경우는 직접 인증서를 해당사이트에 가서 긁어오는 방식을 택해서 작업을 하였다.
git에 cJson을 활용한 부분이고 json의 경우 여러가지 lib과 또는 직접 구현해도 별로 어렵지 않으니 ..
위 소스의 경우 공유메모리를 사용하는 부분이 포함되어 있으니 이부분은 제외하면 될꺼같다.
프로세스가 3개이상 동작중에 데이터를 서로 공유해야하는 상황때문에 이렇게 코딩을 하였으니 참고바람.
이상
728x90
반응형
'나미 > C' 카테고리의 다른 글
함수 포인터(간단하게) (0) | 2023.08.27 |
---|---|
strsep (0) | 2018.10.15 |
문자열 자르기 strtok (0) | 2018.02.05 |
strtol 함수 (0) | 2018.02.05 |
C언어 텍스트 컬러 (0) | 2017.07.12 |
switch case문안에 변수사용하기 (0) | 2017.06.21 |
C언어 파일읽기 (0) | 2017.06.21 |
공유메모리 key 하나로 구조체 배열할당하기 (0) | 2017.03.17 |
hexTobinary(2) (0) | 2017.03.08 |
hexTobinary (0) | 2016.12.16 |