반응형

2019.10.08 - [Linux] - Build your own web server with Fedora linux - 페도라 리눅스로 간단한 웹서버 만들기

2021.08.25 - [Linux] - Linux(Ubuntu) Static IP Configuration - 리눅스(우분투) 고정 IP

 

리눅스(우분투)로 간단한 웹서버를 만들어 보자.

 

패키지 리스트를 업데이트 한다.

 

패키지를 업데이트 한다.

 

apache2를 설치 한다.

 

active 상태인지 확인 한다.

 

■ systemctl 명령어
- start: 서비스 시작
- stop: 서비스 중지
- status: 서비스 상태 확인
- restart: 서비스 재시작
- reload: 서비스를 중지하지 않고 설정값을 반영
- enable: 시스템 재부팅시 자동으로 서비스 실행
- disable: enable 해제

 

서버에 접속하기 위해 IP 주소를 확인 한다.

 

 

다른 컴퓨터로 접속했을때 위와 같은 Default Page가 나오면 정상이다.

 

Default Page를 수정해 보자.

 

Default Page의 HTML 코드. 모두 삭제 한다.

 

위와 같은 코드를 입력한다.

 

다시 서버에 접속해 보면 직접 입력한 내용이 출력 된다.

 

 

PHP를 설치 한다.

 

PHP 코드를 입력하기 위한 파일을 만든다.

 

PHP 정보를 표시하는 간단한 코드를 입력 한다.

 

IP 주소/PHP 파일(http://192.168.171.128/index.php) 로 접속하면 PHP 정보를 표시하는 화면이 표시된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투) 서버 IP를 고정해 보자.

 

현재 IP 주소는 192.168.171.128 이다.

 

DNS Server IP 주소는 192.168.171.2 다.

 

Gateway IP 주소는 192.168.171.2 다.

 

/etc/netplan/00-installer-config.yaml 파일을 열어준다.

 

 

00-installer-config.yaml 의 초기 설정.

 

원하는 IP 주소(192.168.171.200)와 위에서 찾은 IP 정보를 이용해 수정한다.

 

netplan apply를 실행하면 재부팅 하지 않아도 된다.

 

IP가 고정되었다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 OpenCV 이미지(cv::Mat)를 Qt로(QImage::QImage) 디스플레이 해 보자.

(cv::Mat ↔  QImage::QImage)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <opencv2/opencv.hpp>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
    ~Picture();
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass to receive paint events passed in event.
    void drawPicture(QPainter* qp);
    QImage Mat2QImage(cv::Mat const& src);
    cv::Mat QImage2Mat(QImage const& src);
 
private:
    int height;
    int width;
    QImage qtImage;
    cv::Mat cvImage;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    //image.load("Barbara Palvin.png");
    //cvimage = QImage2Mat(image);
 
    //Read images from OpenCV. Not from Qt.
    cvImage = cv::imread("Barbara Palvin.png", cv::IMREAD_COLOR);
    if (cvImage.empty())
    {
        std::cerr << "Image load failed." << std::endl;
 
        exit(EXIT_FAILURE);
    }
 
    cv::Mat tempCvImage;
    cv::cvtColor(cvImage, tempCvImage, cv::COLOR_RGB2GRAY);
 
    qtImage = Mat2QImage(tempCvImage);
    tempCvImage = QImage2Mat(qtImage);
 
    cv::resize(tempCvImage, tempCvImage, cv::Size(), 1.51.5);
    cv::imshow("OpenCV", tempCvImage);
 
    height = qtImage.height();
    width = qtImage.width();
 
    this->resize(width, height);
}
 
Picture::~Picture()
{
 
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the specified name is not used in the body
    // of a function. This can be used to suppress compiler warnings while allowing functions to be
    // defined with meaningful parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, qtImage);
}
 
QImage Picture::Mat2QImage(cv::Mat const& src)
{
    cv::Mat temp;
    cv::cvtColor(src, temp, cv::COLOR_BGR2RGB);
    QImage dest((const uchar*)temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
    dest.bits();
    // Enforce deep copy
    // See documentation of QImage::QImage (const uchar * data, int width, int height, Format format)
 
    return dest;
}
 
cv::Mat Picture::QImage2Mat(QImage const& src)
{
    cv::Mat temp(src.height(), src.width(), CV_8UC3, (uchar*)src.bits(), src.bytesPerLine());
    cv::Mat result; // Deep copy
    cv::cvtColor(temp, result, cv::COLOR_BGR2RGB);
 
    return result;
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Qt");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

 

소스를 입력한다. (qtcv.cpp)

 

컴파일(빌드)하고 실행하면 cv::imshow(), QPainter::drawImage() 모두 잘 표시된다. (OpenCV는 50% 확대)

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 이미지를 디스플레이 해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <QApplication>
#include <QWidget>
#include <QPainter>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass
    // to receive paint events passed in event.
    void drawPicture(QPainter* qp);
 
private:
    int height;
    int width;
    QImage image;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    image.load("Barbara Palvin.png");
    height = image.height();
    width = image.width();
 
    this->resize(width, height);
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the
    // specified name is not used in the body of a function.
    // This can be used to suppress compiler warnings while
    // allowing functions to be defined with meaningful
    // parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, image);
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Picture Example");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

소스를 입력한다. (qt.cpp)

 

컴파일(빌드)하고 실행하면 이미지가 디스플레이된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 GUI 프로그래밍을 해 보자.

 

Qt5를 설치한다.

 

단순한 window를 만드는 소스를 입력한다. (qt.cpp)

 

-fPIC 옵션과 함께 컴파일(빌드)하고 생성된 파일을 실행하면 Simple Example 윈도우가 나타난다.

 

이번엔 같은 소스를 qmake를 이용해 컴파일(빌드)해 보자. -project 옵션과 함께 실행하면 c.pro 파일이 생성된다. (디렉토리 이름.pro)

 

 

c.pro 파일의 내용을 보면 Qt Widgets 모듈이 포함되지 않았다.

 

파일의 끝에 Qt Widgets 모듈을 포함시킨다.

 

qmake, make 명령을 차례로 실행하면 컴파일(빌드)이 완료된다.

 

컴파일(빌드)된 파일을 실행하면 윈도우가 나타난다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 GTK+를 이용해 이미지를 디스플레이 해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <gtk/gtk.h>
 
static gboolean button_press_callback(GtkWidget* event_box, GdkEventButton* event, gpointer data)
{
    g_print("Event box clicked at coordinates %f,%f\n", event->x, event->y);
 
    return TRUE;
}
 
static void activate(GtkApplication* app, gpointer user_data)
{
    GtkWidget* window;
    GtkWidget* image;
    GtkWidget* event_box;
 
    window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "Window");
    gtk_window_set_default_size(GTK_WINDOW(window), 300300);
 
    event_box = gtk_event_box_new();
    gtk_container_add(GTK_CONTAINER(window), event_box);
 
    image = gtk_image_new_from_file("Barbara Palvin.jpg");
    gtk_container_add(GTK_CONTAINER(event_box), image);
 
    g_signal_connect(G_OBJECT(event_box), "button_press_event", G_CALLBACK(button_press_callback), image);
 
    gtk_widget_show_all(window);
}
 
int main(int argc, char** argv)
{
    GtkApplication* app;
    int status;
 
    app = gtk_application_new("sean.s-engineer.example", G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
 
    return status;
}
 
 
 

 

컴파일(빌드)하고 실행하면 창에 이미지가 디스플레이 된다. 클릭하면 좌표가 터미널에 표시된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 GTK+3를 이용해 GUI 프로그래밍을 해 보자.

 

GTK+3를 설치한다.

 

단순한 window를 만드는 예제 소스를 입력한다.

 

컴파일(빌드)하고 실행하면 창이 나타나다. 단순한 창이지만 이동, 종료등의 모든 기본적인 기능을 갖고 있다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <gtk/gtk.h>
 
/* This is a callback function. The data arguments are ignored
 * in this example. More on callbacks below. */
static void hello( GtkWidget *widget,
                   gpointer   data )
{
    g_print ("Hello World\n");
}
 
static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    /* If you return FALSE in the "delete-event" signal handler,
     * GTK will emit the "destroy" signal. Returning TRUE means
     * you don't want the window to be destroyed.
     * This is useful for popping up 'are you sure you want to quit?'
     * type dialogs. */
 
    g_print ("delete event occurred\n");
 
    /* Change TRUE to FALSE and the main window will be destroyed with
     * a "delete-event". */
 
    return TRUE;
}
 
/* Another callback */
static void destroy( GtkWidget *widget,
                     gpointer   data )
{
    gtk_main_quit ();
}
 
int main( int   argc,
          char *argv[] )
{
    /* GtkWidget is the storage type for widgets */
    GtkWidget *window;
    GtkWidget *button;
    
    /* This is called in all GTK applications. Arguments are parsed
     * from the command line and are returned to the application. */
    gtk_init (&argc, &argv);
    
    /* create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    
    /* When the window is given the "delete-event" signal (this is given
     * by the window manager, usually by the "close" option, or on the
     * titlebar), we ask it to call the delete_event () function
     * as defined above. The data passed to the callback
     * function is NULL and is ignored in the callback function. */
    g_signal_connect (window, "delete-event",
              G_CALLBACK (delete_event), NULL);
    
    /* Here we connect the "destroy" event to a signal handler.  
     * This event occurs when we call gtk_widget_destroy() on the window,
     * or if we return FALSE in the "delete-event" callback. */
    g_signal_connect (window, "destroy",
              G_CALLBACK (destroy), NULL);
    
    /* Sets the border width of the window. */
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
    
    /* Creates a new button with the label "Hello World". */
    button = gtk_button_new_with_label ("Hello World");
    
    /* When the button receives the "clicked" signal, it will call the
     * function hello() passing it NULL as its argument.  The hello()
     * function is defined above. */
    g_signal_connect (button, "clicked",
              G_CALLBACK (hello), NULL);
    
    /* This will cause the window to be destroyed by calling
     * gtk_widget_destroy(window) when "clicked".  Again, the destroy
     * signal could come from here, or the window manager. */
    g_signal_connect_swapped (button, "clicked",
                  G_CALLBACK (gtk_widget_destroy),
                              window);
    
    /* This packs the button into the window (a gtk container). */
    gtk_container_add (GTK_CONTAINER (window), button);
    
    /* The final step is to display this newly created widget. */
    gtk_widget_show (button);
    
    /* and the window */
    gtk_widget_show (window);
    
    /* All GTK applications must have a gtk_main(). Control ends here
     * and waits for an event to occur (like a key press or
     * mouse event). */
    gtk_main ();
    
    return 0;
}
 

 

GTK+2 스타일의 예제 소스를 입력해 보자.

 

GTK+2 스타일의 소스를 빌드해도 문제 없다. Hello World 버튼을 클릭한다.

 

터미널 출력까지 잘 된다.

 

반응형
Posted by J-sean
:
반응형

2021/02/07 - [Linux] - Linux make를 이용한 컴파일(빌드) 자동화

 

리눅스에서 소스 코드를 컴파일(빌드)할때 유용한 CMake의 간단한 사용법을 알아 보자.

 

첫 번째 헤더 파일을 만든다. (a.h)

 

헤더 파일의 소스 파일을 만든다. (a.cpp)

 

두 번째 헤더 파일을 만든다. (b.h)

 

헤더 파일의 소스 파일을 만든다. (b.cpp)

 

 

두 헤더 파일과 소스 파일을 사용하는 main() 함수가 포함된 소스 파일을 작성한다.

 

CMakeLists.txt 파일을 만든다.

 

헤더/소스 파일이 있는 디렉토리에 하위 디렉토리 build를 만들고 이동후 cmake 명령을 실행한다. (CMakeLists.txt 파일이 상위 디렉토리에 있으므로 cmake ../ 를 실행해야 한다)

 

Makefile이 생성 되면 make 명령을 실행한다. 빌드가 완료되고 실행파일(main)이 생성된다.

 

반응형
Posted by J-sean
: