성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
[정성태] 만드실 수 있습니다. 단지, Unity 엔진 내의 스크립트와 W...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - PeerFinder를 이용한 Wi-Fi Direct 데이터 통신 예제</h1> <p> 다음과 같은 멋진 글이 있군요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Using PeerFinder from Console: Wi-Fi Direct data transfer in C# ; <a target='tab' href='http://blog.plasticscm.com/2016/09/using-peerfinder-from-console-wi-fi.html'>http://blog.plasticscm.com/2016/09/using-peerfinder-from-console-wi-fi.html</a> </pre> <br /> 사실 아래의 글도 저 블로그를 통해 쓰인 것이었습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 윈도우 데스크톱 응용 프로그램(예: Console)에서 알림 메시지(Toast notifications) 띄우기 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11073'>http://www.sysnet.pe.kr/2/0/11073</a> </pre> <br /> 그나저나, 윈도우의 UWP 기능으로 인해 기존 (classic) 데스크톱 유형의 응용 프로그램도 이런 식으로 혜택을 받게 되니 그저 좋을 따름입니다. ^^<br /> <br /> 자, 그럼 이 글에서는 "<a target='tab' href='http://blog.plasticscm.com/2016/09/using-peerfinder-from-console-wi-fi.html'>Using PeerFinder from Console: Wi-Fi Direct data transfer in C#</a>"에서 설명한 대로 윈도우 콘솔 응용 프로그램에서 Wi-Fi Direct 통신을 하는 프로그램을 만들어 보겠습니다.<br /> <br /> 전에도 말했지만, UWP 기능을 일반 데스크톱 응용 프로그램에서 이용하기 위해선 약간의 사전 작업이 필요한데요. 우선 다음과 같이 .csproj에 TargetPlatformVersion 최소 요구 사항을 8.1로 명시해 줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <TargetPlatformVersion>8.1</TargetPlatformVersion> </pre> <br /> 그리고, 다음의 DLL들을 참조 추가해줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Windows.winmd C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\WindowsBase.dll C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Facades\System.Runtime.dll C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll </pre> <br /> 그다음 클라이언트는 다음과 같이 코드를 추가해 주고,<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.IO; using System.Runtime.InteropServices; using System.Threading.Tasks; using Windows.Networking.Proximity; namespace PeerClient { class Program { static void Main(string[] args) { PeerClient client = new PeerClient(); client.Start(); Console.WriteLine("Press any key to exit..."); Console.ReadLine(); PeerFinder.Stop(); } } class PeerClient { [DllImport("shell32.dll")] static extern int SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID); public PeerClient() { SetCurrentProcessExplicitAppUserModelID("ConsoleApp.Test1"); PeerFinder.Role = PeerRole.Client; PeerFinder.AllowWiFiDirect = true; if ((Windows.Networking.Proximity.PeerFinder.SupportedDiscoveryTypes & Windows.Networking.Proximity.PeerDiscoveryTypes.Browse) != Windows.Networking.Proximity.PeerDiscoveryTypes.Browse) { Console.WriteLine("Peer discovery using Wi-Fi Direct is not supported.\n"); return; } } public async void Start() { PeerFinder.Start(); var peerInfoCollection = await PeerFinder.FindAllPeersAsync(); if (peerInfoCollection.Count == 0) { Console.WriteLine("No peers found"); return; } foreach (var info in peerInfoCollection) { Console.WriteLine("Peer found: {0} - {1}", info.DisplayName, info.Id); Windows.Networking.Sockets.StreamSocket socket = null; try { Task<Windows.Networking.Sockets.StreamSocket> task = PeerFinder.ConnectAsync(info).AsTask(); if (task.Wait(5000) == false) { Console.WriteLine("timeout"); continue; } socket = task.Result; Sender(socket); } catch (Exception e) { Console.WriteLine(e.ToString()); } if (socket != null) { socket.Dispose(); } } } void Sender(Windows.Networking.Sockets.StreamSocket socket) { using (Stream streamWrite = socket.OutputStream.AsStreamForWrite()) using (BinaryWriter writer = new BinaryWriter(streamWrite)) using (Stream streamRead = socket.InputStream.AsStreamForRead()) using (BinaryReader reader = new BinaryReader(streamRead)) { int ini = Environment.TickCount; long totalToSend = 64 * 1024 * 1024; writer.Write(totalToSend); Console.WriteLine("Going to send {0} bytes", totalToSend); byte[] buffer = new byte[totalToSend]; writer.Write(buffer); writer.Flush(); try { reader.ReadBoolean(); } catch { } float MB = totalToSend / 1024 / 1024; float secs = (Environment.TickCount - ini) / 1000; Console.WriteLine("Sent {0} MB in {1} secs = {2:#0.##} MB/s", MB, secs, MB / secs); } } } } </pre> <br /> 서버는 이렇게 추가해 주면 됩니다.<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.IO; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Windows.Networking.Proximity; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { PeerHost peerHost = new PeerHost(); Console.WriteLine("Press any key to exit..."); Console.ReadLine(); peerHost.Stop(); } } class PeerHost { [DllImport("shell32.dll")] static extern int SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID); public PeerHost() { SetCurrentProcessExplicitAppUserModelID("ConsoleApp.Test1"); if ((Windows.Networking.Proximity.PeerFinder.SupportedDiscoveryTypes & Windows.Networking.Proximity.PeerDiscoveryTypes.Browse) != Windows.Networking.Proximity.PeerDiscoveryTypes.Browse) { Console.WriteLine("Peer discovery using Wi-Fi Direct is not supported.\n"); return; } PeerFinder.Role = PeerRole.Host; PeerFinder.DisplayName = "PeerFinderConsoleApp"; PeerFinder.AllowWiFiDirect = true; PeerFinder.ConnectionRequested += ConnectionRequested; PeerFinder.Start(); } void ConnectionRequested(object sender, Windows.Networking.Proximity.ConnectionRequestedEventArgs e) { Console.WriteLine("Connection requested by " + e.PeerInformation.DisplayName + ". " + "Will be accepted automatically."); Windows.Networking.Sockets.StreamSocket socket = null; try { Console.WriteLine("Receiver waiting to connect async"); Task<Windows.Networking.Sockets.StreamSocket> task = PeerFinder.ConnectAsync(e.PeerInformation).AsTask(); if (task.Wait(5000) == false) { Console.WriteLine("timeout"); return; } socket = task.Result; Receiver(socket); } catch { } if (socket != null) { Thread.Sleep(1000); socket.Dispose(); } } static void Receiver(Windows.Networking.Sockets.StreamSocket socket) { Console.WriteLine("Receiver connection happened"); int ini = Environment.TickCount; using (Stream streamRead = socket.InputStream.AsStreamForRead()) using (Stream streamWrite = socket.OutputStream.AsStreamForWrite()) using (BinaryReader reader = new BinaryReader(streamRead)) using (BinaryWriter writer = new BinaryWriter(streamWrite)) { long totalToRead = reader.ReadInt64(); Console.WriteLine("Going to read {0} bytes", totalToRead); long read = 0; byte[] buffer = new byte[32 * 1024 * 1024]; while (read < totalToRead) { long toRead = totalToRead - read; if (toRead >= buffer.Length) { toRead = buffer.Length; } reader.Read(buffer, 0, (int)toRead); Console.WriteLine("{0}/{1}", read, totalToRead); read += toRead; } writer.Write(true); writer.Flush(); float MB = totalToRead / 1024 / 1024; float secs = (Environment.TickCount - ini) / 1000; Console.WriteLine("Received {0} MB in {1} secs = {2:#0.##} MB/s", MB, secs, MB / secs); } } internal void Stop() { PeerFinder.Stop(); } } } </pre> <br /> Wi-Fi Direct가 재미있는 것은, 통신 속도입니다. 제가 집에 있는 USB 외장 하드로 파일을 복사하면 초당 20MB 정도 되는데, Wi-Fi Direct는 위의 실습 코드인 64MB도 1초에 끝내 버립니다. (오히려 Peer 탐색 시간이 더 걸립니다. ^^;)<br /> <br /> 따라서, 상황에 따라 꽤나 유용한 기능이 될 수 있습니다.<br /> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1081&boardid=331301885'>첨부 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> <br /> 참고로, Wi-Fi Direct 통신의 HOST 측 응용 프로그램이 동작하면 제어판의 "Windows Firewall" 항목에 다음과 같이 임시 네트워크가 생성되는 것을 볼 수 있습니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='wifi_direct_network_info_1.png' src='/SysWebRes/bbs/wifi_direct_network_info_1.png' /><br /> <br /> <hr style='width: 50%' /><br /> <br /> 그런데... Wi-Fi Direct 구축 환경이 예상외로 거의 없는 편입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Wi-Fi Direct 지원 여부 확인 방법 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11100'>http://www.sysnet.pe.kr/2/0/11100</a> </pre> <br /> 게다가 실습하는 것도 좀 까다로워서 저 역시 다음과 같은 시행착오를 겪었습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > PeerFinder Wi-Fi Direct 통신 시 Read/Write/Dispose 문제 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11105'>http://www.sysnet.pe.kr/2/0/11105</a> PeerFinder로 Wi-Fi Direct 연결 시 방화벽 문제 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11104'>http://www.sysnet.pe.kr/2/0/11104</a> PeerFinder.ConnectAsync의 결과 값인 Task.Result를 호출할 때 System.AggregateException 예외 발생 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11103'>http://www.sysnet.pe.kr/2/0/11103</a> PeerFinder.FindAllPeersAsync 호출 시 System.UnauthorizedAccessException 예외 발생 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11102'>http://www.sysnet.pe.kr/2/0/11102</a> </pre> <br /> 그 외에 참고 자료로 마이크로소프트의 (약간 오래된) 예제와 설명이 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Proximity sample ; https://code.msdn.microsoft.com/windowsapps/proximity-sample-88129731/ Quickstart: Connecting applications using tapping or browsing (C#) ; <a target='tab' href='https://docs.microsoft.com/en-us/previous-versions/windows/apps/hh465205(v=win.10)'>https://docs.microsoft.com/en-us/previous-versions/windows/apps/hh465205(v=win.10)</a> Quickstart: Publishing and subscribing to messages using tapping (C#) ; <a target='tab' href='https://docs.microsoft.com/en-us/previous-versions/windows/apps/hh465213(v=win.10)'>https://docs.microsoft.com/en-us/previous-versions/windows/apps/hh465213(v=win.10)</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1045
(왼쪽의 숫자를 입력해야 합니다.)