라즈레비파이3 로 무얼 할까 하다가
웹서버를 한번 구축해 볼까 하고 시도해 보았습니다.
이전 포스팅에서 링크가 되어있지만 (http://kjcoder.tistory.com/197)
여러가지 방법이 있으며 제가 시도해서 성공한 내용을 공유해 봅니다.
프로젝트를 생성합니다.
Background 로 돌아가게 할것이기 때문에 아래 처럼 Background Application (IoT) 를 선택합니다. (Visual Studio 2015)
버전은 자신의 라즈베리파이에 맞는 버전에 맞게 설정합니다. (굳이 버전이 안맞아도 최소버전 상위 라면 동작하는 것 같습니다.)
참고로 전 라즈베리파이 버전이 10.0.15063.297 입니다.
이제 위처럼 소스가 만들어 지고 저희가 코딩할 곳은 아래 그림에서 StartupTask.cs 파일입니다.
우선 코딩은 아래와 같습니다. (이해는 나중에....)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using Windows.ApplicationModel.Background;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
// The Background Application template is documented at http://go.microsoft.com/fwlink/?LinkID=533884&clcid=0x409
namespace IoT.BackGroundWebServer
{
public sealed class StartupTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
//
// TODO: Insert code to perform background work
//
// If you start any asynchronous methods here, prevent the task
// from closing prematurely by using BackgroundTaskDeferral as
// described in http://aka.ms/backgroundtaskdeferral
//
taskInstance.GetDeferral();
WebServer server = new WebServer();
while (server.Start() == true)
{ }
}
}
#region WebServer
internal class WebServer
{
private const uint BufferSize = 8192;
public bool Start()
{
try
{
StreamSocketListener listener = new StreamSocketListener();
listener.BindServiceNameAsync("8081").AsTask();
listener.ConnectionReceived += async (sender, args) =>
{
StringBuilder request = new StringBuilder();
using (Windows.Storage.Streams.IInputStream input = args.Socket.InputStream)
{
byte[] data = new byte[BufferSize];
Windows.Storage.Streams.IBuffer buffer = data.AsBuffer();
uint dataRead = BufferSize;
while (dataRead == BufferSize)
{
await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
request.Append(Encoding.UTF8.GetString(data, 0, data.Length));
dataRead = buffer.Length;
}
//In the future, maybe we parse the HTTP request and serve different HTML pages for now we just always push index.html
}
using (IOutputStream output = args.Socket.OutputStream)
{
using (System.IO.Stream response = output.AsStreamForWrite())
{
string page = "";
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
// acquire file
var file = await folder.GetFileAsync("index.html");
var readFile = await Windows.Storage.FileIO.ReadLinesAsync(file);
foreach (var line in readFile)
{
page += line;
}
byte[] bodyArray = Encoding.UTF8.GetBytes(page);
var bodyStream = new MemoryStream(bodyArray);
//iCount++;
var header = "HTTP/1.1 200 OK\r\n" +
$"Content-Length: {bodyStream.Length}\r\n" +
"Connection: close\r\n\r\n";
byte[] headerArray = Encoding.UTF8.GetBytes(header);
await response.WriteAsync(headerArray, 0, headerArray.Length);
await bodyStream.CopyToAsync(response);
await response.FlushAsync();
}
}
};
return true;
}
catch (Exception ex)
{
return false;
}
}
}
#endregion
}
코딩을 보시면 알겠지만 StreamSocketListener 를 이용하여 웹서버를 만들고 기본 화면으로 index.html 파일을 사용하고 있는걸 알 수 있습니다.
또한 포트를 전 8081포트를 사용하는걸로 설정되어있습니다.
index.html 파일을 만듭니다.
내용은 "webserver test" 라고 간단하게 넣었습니다.
프로젝트 속성에서 자신의 라즈베리파이로 디버깅이 가능하도록 설정합니다.
디버깅 설정 방법은 이전 포스팅을 참고 바랍니다 (http://kjcoder.tistory.com/194)
여기서 중요한게 있습니다.
이상태로 그냥 실행하게 되면 라즈베리파이 화면에서는 표시되지 않지만 에러가 발생됩니다.
+ ex {"Access is denied.\r\n\r\nAt least one of either InternetClientServer or PrivateNetworkClientServer capabilities is required to listen for or receive traffic"} System.Exception {System.UnauthorizedAccessException}
접근이 거부된것을 볼수 있습니다.
이 에러를 해결하기 위해서는 아래처럼 진행해야합니다.
프로젝트 속성창에서 라이브러리 탭의 패키지 매니페스트로 접근합니다.
거기서 기능 탭을 선택하면 아래와 같은 화면이 나오게 됩니다.
여기서 기능을 체크해야하는데 아래 두 곳을 추가로 체크해 줍니다.
서버를 만드는 것이기 때문에 서버 기능을 체크해주어야하는 것입니다.
이제 준비는 되었고 디버깅합니다.
Background 로 돌아가게 했으므로 라즈베리파이 화면에는 아무런 변화가 없습니다.
device portal 에서 아래처럼 현재 동작 되고 있는걸 확인 할수 있습니다.
이제 익스플로러 창에서 확인해 봅니다. 제 라즈베리파이3는 ip 192.168.0.23 입니다. 예제에서 포트는 8081 로 했습니다.
위에서 보듯이 제대로 index.html 이 나타나는걸 확인 할수 있습니다.
iptime 을 쓰고 있는데 공유기 설정하고 해보니 외부에서도 이상없이 접근이 되는걸 확인했습니다.
이제 기능을 추가하여 집안의 기기들을 조작하는걸로 가면 좋을것 같네요.^^
아래는 실습한 예제 파일입니다.
'RaspberryPi' 카테고리의 다른 글
(RaspberryPI) 라즈베리파이3 발열문제 (0) | 2017.05.22 |
---|---|
(Windows IoT) 샘플코드 - 링크 (0) | 2017.05.22 |
(RaspberryPI) 라즈베리파이3 로 웹서버 구축하기 (Windows 10 IoT Core) - 링크 (0) | 2017.05.14 |
(RaspberryPI) 원격 접속이 안될때 (Windows 10 IoT Core) (0) | 2017.05.13 |
(RaspberryPI) Visual Studio 로 라즈베리파이에 배포하기 (Windows 10 IoT) (0) | 2017.05.13 |