아두이노 강좌 #48 이더넷 쉴드를 사용하여 Web Server 시작하기
Lucy Archive
Lucy 2023
2020. 11. 11. 01:54

Arduino Ethernet Shield : Web Server

지난 포스트에서는 아두이노 이더넷 쉴드를 사용하여 DHCP와 고정 IP방식으로 LAN에 연결하는 방법에 대해 설명하였습니다. 이번 포스트에서는

이더넷 쉴드를 사용하여 웹 서버를 만드는 방법에 대해 설명

합니다.

개요 : 이해를 위한 설명

Web Server? Client?

네이버와 같은 웹 사이트가 동작하기 위해서는 네이버 사이트를 제공하는 회사와 네이버 사이트를 사용하는 사람들이 필요합니다. 이때 서비스를 제공하는 곳을 서버(Server) 서비스를 이용하는 사람을 클라이언트(Client)라고 말합니다. 네이버에 접속하기 위해 클라이언트 PC의 크롬과 같은 웹 브라우저에서 www.naver.com 같은 도메인 주소를 입력하면, 브라우저는 네이버 서버에 데이터를 요청하고, 웹 페이지에 보여줄 데이터를 수신하여 클라이언트의 웹 브라우저에 네이버 웹 페이지를 보여 줍니다. 


Web Server 와 Web ClientWeb Server 와 Web Client

Arduino Web Server

아두이노 웹 서버를 구축 한다는 의미는 아두이노와 같은 네트워크에 접속해 있는 스마트폰 또는 PC의 웹 브라우저에서 아두이노 IP에 접속하여 아두이노에서 제공하는 웹 페이지를 사용 할 수 있도록 하는 것입니다. 

Arduino Web Server 네트워크 구성Arduino Web Server 네트워크 구성

HTTP

웹 서버와 웹 클라이언트의 통신은 서버 PC와 클라이언트의 웹 브라우저와 통신을 말합니다. 이때 사용되는 통신 방식이 HTTP 입니다. 웹 서버 PC는 하나이지만, 웹 브라우저의 종류는 다양하기 떄문에 HTTP란 통신 규격으로 통신(데이터 송신,수신)을 하게 됩니다. 

아두이노에서 웹 서버를 구축하게 되면 아두이노와 클라이언트의 웹 브라우저와 HTTP통신 방식으로 데이터를 주고 받습니다.

HTML, CSS, Javascript

HTML, CSS, Javascript는 웹 페이지를 구성하는 언어입니다. 웹 브라우저에서 보여지는 모든 화면은 이 3가지의 언어를 사용하여 만들어집니다. 

즉, 클라이언트의 브라우저에서 웹 서버에 접속하면 HTTP 통신 방식으로 웹 페이지 데이터(HTML, CSS, Javascript 등)를 수신하여 브라우저에서 웹 페이지 화면을 표시 합니다. 


아두이노 웹 서버

하드웨어

아두이노로 이더넷을 연결하기 위해 Arduino Uno 보드와 Arduino Ethernet Shield2 보드를 사용하였습니다. 이번 설명에서는 SD-Card는 사용하지 않고, Arduino Uno의 메모리만을 사용하여 구현 합니다. 

Arduino Ethernet Shield2 연결Arduino Ethernet Shield2 연결

웹 페이지 준비

아래 그림은 아두이노 웹 서버에서 보여줄 웹 페이지의 코드와 브라우저에서 해당 코드를 실행 한 화면입니다. HTML 코드를 본문에 삽입 할 수 없어 첨부 파일로 Index.html 을 참고로 첨부하였습니다. 

index.html

아두이노 웹 페이지(좌) HTML 코드 (우) 브라우저

아두이노 코드

아래 코드는 192.168.0.50 IP 주소를 가지는 아두이노 웹 서버 예시입니다. 아두이노와 같은 네트워크에 연결된 장치의 웹 브라우저에서 192.168.0.50으로 접속하면 위의 HTML 코드를 전송합니다. 아래의 코드는 하단의 [각주:1]링크를 참조하여 수정하였습니다. 

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
#include <SPI.h>
#include <Ethernet.h>
 
byte mac[] = {0x900xA20xDA0x100x530x07}; // MAC Address 
IPAddress ip(192168050); // IP Address
EthernetServer server(80); // Port 80 is default for HTTP
 
void setup()
{
    // You can use Ethernet.init(pin) to configure the CS pin
    //Ethernet.init(10);  // Most Arduino shields
    //Ethernet.init(5);   // MKR ETH shield
    //Ethernet.init(0);   // Teensy 2.0
    //Ethernet.init(20);  // Teensy++ 2.0
    //Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
    //Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin(); // Start to listen for clients
    Serial.begin(115200);
}
 
void loop()
{
    EthernetClient client = server.available();  // try to get client
 
    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                Serial.print(c);
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
                    // send web page
                    client.println("<!DOCTYPE html>");
                    client.println("<html lang=\"en\">");
                    client.println("<head>");
                    client.println("<meta charset=\"UTF-8\">");
                    client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">");
                    client.println("<title>Arduino Web Page</title>");
                    client.println("</head>");
                    client.println("<body>");
                    client.println("<h1>Arduino Web Page</h1>");
                    client.println("<p>Hello World! This is arduino Web page!</p>");
                    client.println("</body>");
                    client.println("</html>");
                    break;
                }
                if (c == '\n') {
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    currentLineIsBlank = false;
                }
            } 
        } 
        delay(1);  
        client.stop(); // close the connection
    }
}
cs

코드 설명

선언부

  • MAC 주소 입력, IP 주소 입력, EthernetServer 클래스 인스턴스 생성 및 초기화
  • 4줄 : MAC 주소를 입력 합니다. 일반적으로 보유하고 있는 이더넷 쉴드 하단에 스티커가 부착되어 있습니다.
  • 5줄 : 네트워크 IP범위에 맞는 적절한 IP주소를 입력 합니다.
  • 6줄 : 포트 번호를 80으로 초기화 - 일반 적으로 웹 서버는 80번 포트 번호 사용

void setup()

  • 이더넷 초기화, 이더넷 서버 시작, 시리얼 포트 시작
  • 10~16줄 : Arduino Ethernet Shield 가 아닌 경우 적절한 Ethernet.init(pin) 코드 삽입 필요
  • 17줄 ; 이더넷 초기화 - 고정 IP사용
  • 18줄 : 웹 서버 시작 - 클라이언트 호출 기다림 시작
  • 19줄 : 시리얼 포트 시작 - 수신된 HTTP 메세지 출력 용도로 사용

void loop()

  • 클라이언트가 접속하면 웹페이지 HTML 데이터를 송신
  • 24줄 : 클라이언트가 접속하면 이더넷 클라이언트 클래스 객체를 생성
    • 클라이언트와의 통신은 서버가 직접 하지 않고, 클라이언트와 통신하기 위해 생성된 클라이언트 객체와 통신을 합니다.
  • 26줄~65줄 : 클라이언트가 접속하면 실행되는 if문
    • 27줄 : 클라이언트의 HTTP 요청이 완료되었는지 확인 하기 위한 boolean 변수 생성 (하단 설명 참조)
    • 28줄 : 클라이언트가 연결 된 상태일 때 실행되는 반복문
    • 29줄 : 클라이언트로부터 수신된 메세지가 있는 경우 실행되는 if문
    • 30줄~31줄 : 클라이언트로부터 수신된 메세지가 저장된 수신 버퍼에서 데이터를 하나씩 읽어서 시리얼 포트로 출력
    • 34줄 : 클라이언트로부터 HTTP 요청이 완료되면 실행되는 if문
    • 36~39줄 : HTTP HEAD 응답
    • 41~52줄 : HTTP BODY 응답 - 웹 페이지 HTML 코드
    • 55~56줄 : HTTP 수신 버퍼에서 읽은 문자가 \n(New Line)인 경우 currentLineIsBack 을 True로 설정
    • 58~59줄 : HTTP 수신 버퍼에서 읽은 문자가 \n(New Line) 또는 \r(Carriage Return) 아닌 경우 currentLineIsBack을 False로 설정

HTTP Request 메세지

위의 코드를 실행 후 클라이언트의 웹 브라우저에서 192.168.0.50으로 접속하면 브라우저에서 아두이노로 HTTP 규격에 따라 아래와 같은 HTTP 호출 메세지가 전달됩니다. 아래 그림과 같이 클라이언트의 HTTP 요청 메세지는 마지막에 한 줄을 띄우도록 약속되어있습니다. 

위 코드의 34번 줄 코드는 HTTP 수신 버퍼에서 읽은 문자가 \n이고 currentLineIsBlank가 True인 경우 Client Reuqest 메세지가 완료되었다고 판단하고 실행되는 if문입니다.

HTTP Request 메세지HTTP Request 메세지

실행 결과

아래 그림은 같은 네트워크에 있는 PC의 웹 브라우저에서 아두이노 IP인 192.168.0.50으로 접속 후 보여지는 웹 페이지와 아두이노의 시리얼 메세지 출력 화면입니다. 

Arduino Web Server 실행 결과Arduino Web Server 실행 결과

관련포스트

👉 아두이노 이더넷 관련글 목록 보기

👉 아두이노 관련글 전체 목록 보기


  1. https://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/basic-web-server/ [본문으로]