ADO.NET 클래스는 크게 두 개의 컴포넌트로 나누어져 있다. 즉, 물리적인 데이터 저장소와의 커뮤니케이션을 다루는 데이터 공급자와 실제 데이터를 나타내주는 DataSet으로 나누어진다. 이들 두 가지 컴포넌트들은 모두 WebForm이나 WinForm과 같은 데이터 사용자와 통신 할 수 있다.


데이터 공급자

데이터 공급자 컴포넌트는 데이터 소스에 대하여 특별한 역활은 한다. .NET프레임워크에 포함되어 있는 두 개의 데이터 공급자는 서로 동일한 객체를 포함하고 있다. 포함하고 있는 각각의 객체가 서로 다른 이름을 가지고 있고 일부 속성과 메서드가 다르지만 이들은 동일한 객체이다. 


Connection

Connection 객체는 데이터 소스와의 물리적인 연결을 나타낸다. Connection객체의 속성은 데이터 공급자,연결하고자 하는 데이터 소스와 데이터베이스, 그리고 연결하는 동안 사용할 문자열을 결정 짓는다. Connection객체의 메서드는 연결을 열거나 닫고, 데이터베이스를 변경하는 트랜잭션을 관리한다.


Command

Command객체는 데이터 소스에 대해 실행될 SQL문 또는 저장프로시저를 나타낸다. Connection객체와는 상관없이 독립적으로 Command객체를 생성하고, 실행 할 수 있다. 또한 DataSet과 데이터 소스와의 통신을 위해 DataAdapter 객체가 Command객채를 사용한다. Command객체는 단일 값, 한개 또는 그 이상의 행 집합, 또는 전혀 값을 리턴하지 않는 SQL문과 저장 프로시저를 지원할 수 있다.


DataReader

DataReader는 데이터 소스의 데이터 스트림을 전방향 및 읽기전용으로 포함하기 위한 빠르고 오버헤드가 적은 객체이다. DataReader 객체는 코드에 직접 생성할 수 없고, 오직 Command객체의 ExecuteReader 메서드를 호출할 때만 생성할 수 있다.


DataAdapter

DataAdapter는 데이터 공급자 객체들 중에서 기능적으로 가장 복잡한 객체이다. DataAdapter 는 Connection과 DataSet 사이의 브릿지를 제공한다. DataAdapter는 네 개의 Command객체, SelectCommand, UpdateCommnad, InsertCommand, DeleteCommand를 포함한다. DataSet을 채우기 위해서 SelectCommand를 사용하고, 다른 나머지 세개의 객체는 병경내용을 다시 데이터 소스에 전달할 때 사용한다.


DataSets

DataSet은 데이터를 나타내기 위한 메모리 상주형 데이터이다. DataSet의 구조는 그림과 같고, 테이블과 테이블 사이의 관계로 구성된 관계형 데이터베이스를 간단히 나타낸 형태와 같다고 볼 수 있다. DataSet이 항상 데이터 소스와 연결되어 있지 않다는 것이 중요하다. DataSet이 가지고 있는 데이터를 어디에서 가져왔는지 알지 못하지만, 실제적으로는 여러 데이터 소스의 데이터를 포함할 수 있다.


DataSet은 DataTableCollection과 DataRelationCollection이라는 두 개의 주요한 객체로 구성된다. DataTableCollection은 0개 또는 그 이상의 DataTable 객체를 포함한다. 그리고 DataTable은 차례로 Columns,Rows,Constraints 의 세 개의 컬렉션으로 구성되어 있다. 

DataRelationCollection은 0개 또는 그 이상의 DataRelation을 포함한다.




1.  저장프로시저란?

저장 프로시저(Stored Procedure)는 일련의 쿼리를 마치 하나의 함수처럼 실행하기 위한 쿼리의 집합입니다. 저장프로시저를 잘 만들면 프로그램 내에서 복잡하게 코드를 구성하는 것을 막고 원하는 결과를 얻을 수 있습니다.




2.  저장프로시저 사용방법

 

저장프로시저를 사용하기 위해서는 먼저 MS SQL서버에 접속한 후 저장프로시저를 클릭해서 새 저장프로시저 추가를 누르면 저장프로시저가 생성됩니다.



저장프로시저 추가버튼을 누르면 다음과 같은 창이 생성됩니다. 여기서 CREATE PROCEDURE 라고 나오는 것은 프로시저를 새로 만들어야 하기 때문입니다. 한번 생성해서 저장한 후에는 ALTER PROCEDURE 라고 바뀌는데 이것은 저장프로시저를 수정하는 것을 뜻합니다. 첫 행 아래 부분에 괄호로 되어있는 곳에 매개변수를 넣어주는 곳인데요. 여기서 변수나 매개변수를 쓸 때는 @를 앞에 붙여 주셔야 합니다.

예를들면 @name varchar(20), @num int 이런식으로 사용할 수 있습니다. 그리고 AS 아래 부분에는 수행해야 할 쿼리문이나 다른 저장프로시저를 호출하는 코드를 작성 하는 곳입니다.

 


3.  저장프로시저 예제

 

      -       회원가입에서 호출된 저장프로시저인 CheckID

ALTER PROCEDURE dbo.CheckID

(

           @id varchar(10),

           @check int output

)

AS

           if Exists (select *from Member where m_id = @id)

                     Begin

                                set @check = 1

                     End

          

           else

                     Begin

                                set @check = 0

                     End

          

           RETURN

 

 

 CheckID는 Member테이블 내에 매개변수로 넘어온 id와 같은 id가 있는지 존재여부를 판단해서 output으로 넘어온 변수에 값을 세팅해주는 역할을 합니다. 이 프로시저는 아래에 나오는 NewMember 에서 사용되는데요. 이 프로시저를 활용한 NewMember 저장프로시저에 대해서 알아보겠습니다.

 

 

 

 -       계층화된 저장프로시저를 이용해서 회원가입.

ALTER PROCEDURE dbo.NewMember

(

           @id varchar(10),

           @pw varchar(10),

           @name varchar(10)    

)

AS

           declare @check int

          

           Exec CheckID @id,@check output

 

           if @check != 1

                     Begin

                                insert into Member values(@id,@pw,@name,@check)

                     End    

          

           RETURN

 

NewMember 저장프로시저에서는 id와 pw, name을 매개변수로 받아와서 Member 테이블에 저장시키는 작업을 수행 하는 것입니다. 회원가입을 할 때 id가 중복되면 안되기 때문에 CheckID라는 저장프로시저를 호출합니다. Exec는 저장프로시저에서 다른 저장프로시저를 호출할 때 사용하는 키워드 입니다.


Declare AS 내부에 변수를 선언할 때 사용되는 키워드 입니다여기서 check라는 변수를 output 으로 전달하고 있습니다. output이란 C#에서 out과 같은 기능을 하는 것으로 호출된 저장프로시저 내부에서 check에 값을 넣어주면 값이 저장되서 사용할 수 있게 됩니다.



저장프로시저를 마우스 오른쪽 버튼 클릭한 후 실행을 하면 다음과 같은 창이 나오고



실행창에서 값을 입력해 저장프로시저가 제대로 작동하는지 확인 할 수 있습니다


제대로 실행되면 1개 행이 영향을 받았다고 출력됩니다.

중복아이디가 있어서 회원가입이 되지 않은 경우에는 0개 행이 영향을 받았다고 나옵니다.

그리고 저장프로시저에서 RETURN 반환 값을 지정할 경우 RETURN_VALUE에 반환되는 값이 출력되게 됩니다.



System.Reflection 네임스페이스의 클래스와 System.Type을 사용하면 로드된 어셈블리와 이 어셈블리에 정의된 클래스, 인터페이스, 값 형식 등의 형식에 대한 정보를 얻을 수 있습니다.

리플렉션을 사용하여 런타임에 형식 인스턴스를 만든 다음, 이 형식 인스턴스를 호출하고 액세스할 수도 있습니다.

 

먼저 System.Type 클래스에 대해서 알아 보겠습니다.

System.Reflection 네임스페이스에 정의되어 있는 많은 항목들이 추상 클래스인 System.Type클래스를 사용하고 있습니다.

System.Type클래스의 대략적인 맴버를 정리 해보겠습니다.

IsAbstract

이 속성들을 이용하면 참조하고 있는 Type에 대한 여러 가지 기본적인 정보를 알아낼 수 있다

IsArray

IsClass

IsCOMObject

IsEnum

IsInterFace

IsPrimitive

IsNestedPublic

IsNestedPrivate

IsSealed

IsValueType

GetConstructors()

이 메소드들을 이용하면 알아내고 싶은 항목들을 나타내는 배열을 얻을 수 있습니다.

GetEvents()

GetFields()

GetInterfaces()

GetMembers()

GetNestedTypes()

GetProperties()

FindMembers()

검색 기준에 기반해서, MemberInfo형식을 배열을 반환한다.

GetType()

이 정적 메소드는 해당 문자열 이름에 대한 Type인스턴스를 반환한다.

InvokeMember()

이 메소드를 이용하면 해당 아이템에서 late바인딩을 이용할 수 있다.

 

System.Type에 대해서 좀더 자세히 알고 싶으시면 아래 주소를 참조해주세요

http://msdn.microsoft.com/ko-kr/library/system.type.aspx

 

다음으로 System.Reflection 네임스페이스에 대해서 알아 보도록 하겠습니다.

 

System.Reflection 네임스페이스의 멤버

Assembly

이 클래서에는 어셈블리를 로드하고 조사하고 조작하하는 데 이용할 수 있는 여러 개의 메소드들이 포함되어 있다.

AssemblyName

이 클래스를 이용하면 어셈블리 자체에 대한 여러가지 상세한 정보를 알아낼 수 있다.

EventInfo

해당 이벤트에 대한 정보를 가진다.

FieldInfo

해당 필드에 대한 정보를 가진다.

MemberInfo

이것은EventInfo, FieldInfo, MethodInfo,

PropertyInfo 형식에 대한 공통의 조작을 정의하는 추상 기본 클래스 이다.

MethodInfo

해당 메소드에 대한 정보를 포함한다.

Module

다중 파일 어셈블리에 있는 해당 모듈에 접근하는 데 이용할 수 있다.

ParameterInfo

해당 매개변수에 대한 정보를 가진다.

PropertInfo

해당 속성에 대한 정보를 가진다.

 

System.Reflection 네임스페이스에 대해서 좀더 자세히 알고 싶으시면 아래 주소를 참조해주세요

http://msdn.microsoft.com/ko-kr/library/system.reflection.aspx

 

아래의 클래스를 Dll로 만들었습니다.

HelloLib.Dll

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace HelloLib

{

    public delegate void MyDele(int a);

    class ExampleClass

    {

        public  event MyDele del=null;

        public int num;

        public string name=string.Empty;

        Dictionary<intstring> dic = new Dictionary<intstring>();

    

        public int Num

        {

            get

            {

                return num;

            }

            set

            {

                num = value;

            }

        }

        public ExampleClass()

        {

           

        }       

        public void Foo()

        {

 

            if (del != null)

            {

                del(4);

            }

            else

            {

                Console.WriteLine("이벤트 핸들러가 연결 안 됨");

            }

        }

        public int Soo(int a, int b)

        {

            return a + b;

        }

        public static int Koo(int a, int b)

        {

            return a * b;

        }

        public string this[int key]

        {

            get

            {

                if (dic.ContainsKey(key))

                {

                    return dic[key].ToString();

                }

                return string.Empty;               

            }

            set

            {

                dic[key] = value;

            }

        }

    }

}

 

 


Dll을 사용하는 방법들은 많습니다.

여태까지는 Dll을 만들면 아래 그림과 같은 참조추가를 하였습니다.



하지만 리플렉션은 컴파일시에 Dll을 참조하는 것이 아니라 런타임시에 Dll의 형식을 알아와 해당 정보에 맞게 사용할 수 있게해줍니다.

 

아래 코드를 통해서 리플렉션에 대해서 알아 보도록 하겠습니다.

1.어셈블리 로딩

사용할 Dll을 지정해 줍니다.

Assembly asm = Assembly.Load("HelloLib");

 

2. 특정 형식의 리플렉션된 type개체 생성

해당Dll의 네임스페이스 안에 사용할 클래스를 지정해서

그 클래스 형식의 정보를 가지는 type개체를 생성합니다.

Type type = asm.GetType("HelloLib.ExampleClass");

 

3. 리플렉션된 type의 원 형식의 개체 생성

사용해 왔던 코드에서 비교하면 new와 같은 CreateInstance로 해당 클래스의 정보를 가지는 type개체를 가지고 obj를 생성합니다.

(만일 사용되는 클래스가 객체 생성을 필요치 않는 static과 같은 클래스라면 해당 코드는 생략해도 됩니다.)

Object obj = Activator.CreateInstance(type);

 

4. 멤버 메소드 리플렉션

HelloLib내의 Soo함수를 사용하기

아래 와 같은 방식으로 Dll내의 함수들을 사용할 수 있습니다.

사용하고자 하는 해당 함수의 정보를 GetMethod를 이용해 Method정보를 가질 수 있는 MethodInfo mi에게 정보를 가지게 하고 해당 Soo함수의 매개변수의 개수에 맞는 Object[] 배열을 만들어 거기에 넣어줍니다.

MethodInfo mi = type.GetMethod("Soo");

Object[] objs = new object[2];

objs[0] = 2;

objs[1] = 3;

 

 

5. 리플렉션된 메소드를 통한 원 개체의 원 메소드를 호출

Method 내의 Invoke를 통해 함수를 실행 시킬 수 있습니다.

해당함수의 정보를 가지고 있는 obj개체와 함수 구동에 필요한 매개변수들을 배열로 가진 objs를 넣어주면 해당함수가 실행됩니다.

함수를 선언해놓은 대로 return값을 받아 올 수 있습니다.

int re = (int)mi.Invoke(obj, objs);

Console.WriteLine("re:{0}", re);

 

6. 정적 멤버 메소드 리플렉션

mi = type.GetMethod("Koo");

           

 

//리플렉션된 정적 메소드를 통한 원 메소드를 호출

objs = new object[2];

objs[0] = 3;

objs[1] = 4;

re=(int) mi.Invoke(null, objs); //첫번째 인자가 null을 주는 것이 차이점           

Console.WriteLine("re:{0}", re);

 

7. 멤버 메소드 리플렉션

매개 변수가 없는 함수를 호출 하는 방식입니다.

mi = type.GetMethod("Foo");//리플렉션된 메소드를 통한 원 개체의 원 메소드를 호출

mi.Invoke(obj, null);

 

8. 프로퍼티 리플렉션

해당클래스의 속성을 이용하는 방식입니다 일단 GetProperty를 이용해서 프로퍼티의 정보를 PropertyInfo pi에 가지고 옵니다.

주의점은 as연산자를 사용할 수 없다는 것입니다.

이유는 as는 참조형식에 대한 변환이기 때문입니다.

PropertyInfo pi = type.GetProperty("Num");

 

int num = (int)pi.GetValue(obj, null); //리플렉션된 프로퍼티를 통해 원 개체의 원 프로퍼트의 Get사용

Console.WriteLine("num:{0}", num);

 

MethodInfo mi3 = pi.GetSetMethod();//리플렉션된 프로퍼티를 통해 Set메소드 리플렉션

object[] objs2 = new object[1];

objs2[0] = 7;

 

mi3.Invoke(obj, objs2); //리플렉션된 Set메소드를 통해 원 개체의 원 프로퍼티의 Set사용

 

mi3 = pi.GetGetMethod();//리플렉션된 프로퍼티를 통해 Get메소드 리플렉션

 

num = (int)mi3.Invoke(obj, null); //리플렉션된 Set메소드를 통해 원 개체의 원 프로퍼티의 Get사용

Console.WriteLine("num:{0}", num);

 

9.인덱서를 리플렉션으로 사용하는 방법입니다.

//인덱서의 set  리플렉션의

mi5 = type.GetMethod("set_Item");

objs = new object[2];

objs[0] = 7;

objs[1] = "하이" ;

//리플렉션 된 인덱서의 set을 통해 원 개체의 인덱서 set사용

mi5.Invoke(obj, objs);           

 

//인덱서의 get  리플렉션의

mi5 = type.GetMethod("get_Item");

objs = new object[1];

objs[0] = 7;

//리플렉션 된 인덱서의 get을 통해 원 개체의 인덱서 get사용

Console.WriteLine(mi5.Invoke(obj, objs).ToString());

 

10.델리게이트 와 이벤트를 리플렉션으로 사용하는 방법입니다.

//델리게이트 형식 리플렉션

Type type2 = asm.GetType("HelloLib.MyDele");

 

//이벤트 리플렉션

EventInfo ei = type.GetEvent("del");

 

//접근 권한이 public 하지 않으면서 정적인 메소드 리플렉션

MethodInfo mi8 = typeof(Program).GetMethod("DoIt"BindingFlags.NonPublic |BindingFlags.Static);

 

//형식 리플렉션

Type type3 = Type.GetType("AboutReflection.Program");           

           

//델리게이트가 리플렉션된 형식과 리플렉션된 메소드를 통한 델리게이트 개체 생성

Delegate d = Delegate.CreateDelegate(type2,mi8);

 

 

//리플렉션된 이벤트를 가지고 원 개체에 델리게이트(이벤트 핸들러) 추가

ei.AddEventHandler(obj, d);



ADO.NET

ADO.NET은 Microsoft사가 내어 놓은 Daga Access기술 중에 가장 최근 기술 입니다.

ODBC의 공통 액세스 계층을 두고 공통 액세스 계층에서 해당 데이터베이스에 맞는 ODBC Driver를 호출하는 식으로 데이터베이스와의 종송석을 끊을 수 있었습니다. 하지만 여기서 문제는 ODBC는 C언어와 같은 저수준 언어를 위한 API만 제공되고 있을뿐 고수준 언어에서 활용하기에는 적절하지 못했던 것 입니다.
그래서 DAO가 새롭게 제공되고 OLEDB가 나타났습니다. OLEDB는 ODBC와 유사하게 동작하지만 그보다 사용하기 쉽고 유연하며 강력한 기능들을 제공했습니다. 또한 COM을 기반으로 하고 있으며 트랜잭션에 관련된 기능들과 연결 폴링과 같은 많은 기능들이 제공되었습니다.하지만 강력한 기능을 제공하면서 사용은 어려워지게 되었습니다. 그래서 ADO가 등장하게 되었습니다. ADO는 사용하기 어려운 OLEDB를 살짝 포장해서 사용하기 쉽게 간추려 정리해 놓은 버전이라고 생각하시면 됩니다. ADO에서는 복잡한 부하 기능과는 상관없이 면 줄마능로 간단하게 데이터 베이스를 접근하고 데이터 변경을 할 수 있는 아주 간단한 구조와 직관적인 형태를 갖추게 됩니다.


DOOmsDay.zip




'Programing > C#&.Net' 카테고리의 다른 글

OpenAPI, XML파싱  (0) 2016.11.30
계산기 예제  (0) 2016.11.30
노트북 블루투스 + 안드로이드 폰 연동  (0) 2016.11.30
speech To Text  (0) 2016.11.30
회원관리 연습  (0) 2016.11.30

calculator.zip


'Programing > C#&.Net' 카테고리의 다른 글

OpenAPI, XML파싱  (0) 2016.11.30
D Day 프로그램  (0) 2016.11.30
노트북 블루투스 + 안드로이드 폰 연동  (0) 2016.11.30
speech To Text  (0) 2016.11.30
회원관리 연습  (0) 2016.11.30

Windows to Android bluetooth Test.zip

블루투스로가버렷.zip




노트북 블루투스와 안드로이드 폰간의 통신



블루투스 통신을 하기 전에 노트북에서 블루투스 장치관리자를 통해 핸드폰 블루투스를 연결해야 한다.

SEV-E160S  내 핸드폰을 연결 한것을 확인 할 수 있다. (갤럭시 노트1 , 안드로이드 4.1.2)



노트북에서 블루투스통신을 하기 위해 c#으로 프로그램을 만들었다.



핵심은 InTheHand.Net.Personal.dll 이다. 이 DLL에서 제공해주는 라이브러리를 사용하여 블루투스 연결을 하였다.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using InTheHand.Net.Sockets;
using InTheHand.Net.Bluetooth;
using InTheHand.Windows.Forms;
using InTheHand.Net.Bluetooth.AttributeIds;
using System.IO;

namespace Bluetooth_ServerSide
{
    public partial class Form1 : Form
    {
        // Threads
        Thread AcceptAndListeningThread;

        // helper variable
        Boolean isConnected = false;
        
        //bluetooth stuff
        BluetoothClient btClient;  //represent the bluetooth client connection
        BluetoothListener btListener; //represent this server bluetooth device

        public Form1()
        {

            InitializeComponent();


            //when the bluetooth is supported by this computer

            if (BluetoothRadio.IsSupported)
            {

                UpdateLogText("Bluetooth Supported!");
                UpdateLogText("—————————–");
                
                //getting device information
                UpdateLogText("Primary Bluetooth Radio Name : " + BluetoothRadio.PrimaryRadio.Name);
                UpdateLogText("Primary Bluetooth Radio Address : " + BluetoothRadio.PrimaryRadio.LocalAddress);
                UpdateLogText("Primary Bluetooth Radio Manufacturer : " + BluetoothRadio.PrimaryRadio.Manufacturer);
                UpdateLogText("Primary Bluetooth Radio Mode : " + BluetoothRadio.PrimaryRadio.Mode);
                UpdateLogText("Primary Bluetooth Radio Software Manufacturer : " + BluetoothRadio.PrimaryRadio.SoftwareManufacturer);
                UpdateLogText("—————————–");

                //creating and starting the thread
                AcceptAndListeningThread = new Thread(AcceptAndListen);

                AcceptAndListeningThread.Start();

            }
            else
            {
                UpdateLogText("Bluetooth not Supported!");
            }
        }
        StreamReader srReceiver;
        private delegate void UpdateLogCallback(string strMessage);

        private void ReceiveMessages()
        {
            // Receive the response from the server
            srReceiver = new StreamReader(btClient.GetStream());

            // If the first character of the response is 1, connection was successful
            string ConResponse = srReceiver.ReadLine();

            // If the first character is a 1, connection was successful
            if (ConResponse[0] == '1')
            {
                // Update the form to tell it we are now connected
                this.Invoke(new UpdateLogCallback(this.UpdateLogText), new object[] { "Connected Successfully!" });
            }
            else // If the first character is not a 1 (probably a 0), the connection was unsuccessful
            {
                string Reason = "Not Connected: ";

                // Extract the reason out of the response message. The reason starts at the 3rd character
                Reason += ConResponse.Substring(2, ConResponse.Length - 2);

                // Exit the method
                return;
            }
            // While we are successfully connected, read incoming lines from the server
            while (isConnected)
            {
                // Show the messages in the log TextBox
                this.Invoke(new UpdateLogCallback(this.UpdateLogText), new object[] { srReceiver.ReadLine() });
            }
        }

        //the function of the thread
        public void AcceptAndListen()
        {
            while (true)
            {
                if (isConnected)
                {
                    //TODO: if there is a device connected
                    //listening
                    try
                    {
                        UpdateLogTextFromThread("Listening….");
                        NetworkStream stream = btClient.GetStream();

                        Byte[] bytes = new Byte[512];

                        String retrievedMsg = "";

                        stream.Read(bytes, 0, 512);

                        stream.Flush();

                        for (int i = 0; i < bytes.Length; i++)
                        {
                            retrievedMsg += Convert.ToChar(bytes[i]);

                        }

                        UpdateLogTextFromThread(btClient.RemoteMachineName + " : " + retrievedMsg);
                        UpdateLogTextFromThread("");

                        if (!retrievedMsg.Contains("servercheck"))
                        {

                            sendMessage("Message Received!");
                        }
                        ReceiveMessages();
                    }
                    catch (Exception ex)
                    {
                        UpdateLogTextFromThread("There is an error while listening connection");
                        UpdateLogTextFromThread(ex.Message);
                        isConnected = btClient.Connected;
                    }
                }
                else
                {
                    //TODO: if there is no connection
                    // accepting
                    try
                    {
                        btListener = new BluetoothListener(BluetoothService.RFCommProtocol);
                        
                        UpdateLogTextFromThread("Listener created with TCP Protocol service " + BluetoothService.RFCommProtocol);
                        UpdateLogTextFromThread("Starting Listener….");
                        btListener.Start();
                        UpdateLogTextFromThread("Listener Started!");
                        UpdateLogTextFromThread("Accepting incoming connection….");
                        btClient = btListener.AcceptBluetoothClient();
                        isConnected = btClient.Connected;
                        UpdateLogTextFromThread("A Bluetooth Device Connected!");
                    }
                    catch (Exception e)
                    {
                        UpdateLogTextFromThread("There is an error while accepting connection");
                        UpdateLogTextFromThread(e.Message);
                        UpdateLogTextFromThread("Retrying….");
                    }
                }
            }
        }
        //this section is to create a method that allow thread accessing form’s component
        //we can’t update the text of the textbox directly from thread, so, we use this delegate function
        
        delegate void UpdateLogTextFromThreadDelegate(String msg);
        public void UpdateLogTextFromThread(String msg)
        {
            if (!this.IsDisposed && logsText.InvokeRequired) 
            {
                logsText.Invoke(new UpdateLogTextFromThreadDelegate(UpdateLogText), new Object[]{msg});
            }
        }
        //just ordinary function to update the log text.
        //after updating, we move the cursor to the end of text and scroll it to the cursor.
        public void UpdateLogText(String msg)
        {
            logsText.Text += msg + Environment.NewLine;
            logsText.SelectionStart = logsText.Text.Length;
            logsText.ScrollToCaret();
        }
        //function to send message to the client
        public Boolean sendMessage(String msg) 
        {
            try
            {
                if (!msg.Equals(""))
                {
                    UTF8Encoding encoder = new UTF8Encoding();
                    NetworkStream stream = btClient.GetStream();
                    stream.Write(encoder.GetBytes(msg + "\n"), 0, encoder.GetBytes(msg).Length);
                    stream.Flush();
                    
                }
            }
            catch (Exception ex)
            {
                UpdateLogTextFromThread("There is an error while sending message");
                UpdateLogTextFromThread(ex.Message);
                try
                {
                    isConnected = btClient.Connected;
                    btClient.GetStream().Close();
                    btClient.Dispose();
                    btListener.Server.Dispose();
                    btListener.Stop();
                }
                catch (Exception)
                {
                }
            
                return false;
            }
            
            return true;
        }
        //when closing or exiting application, we have to close connection and aborting the thread.
        //Otherwise, the process of the thread still running in the background.
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                AcceptAndListeningThread.Abort();
                btClient.GetStream().Close();
                btClient.Dispose();
                btListener.Stop();
                FormClosed += new FormClosedEventHandler(Form1_FormClosed);
            }
            catch (Exception)
            {
            }
        }

        void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            Close();
        }
        private void sendBtn_Click(object sender, EventArgs e)
        {
            sendMessage(messageText.Text);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            sendMessage(messageText.Text);
            sendMessage(textBox1.Text);

            messageText.Clear();
            textBox1.Clear();
        }
    }
}


전체적인 구조는 기본적인 통신 구조와 같다. 

윈도우 프로그램은 서버 역활을 하며 접속을 기다린다.


안드로이드 프로그램은 오픈소스인 BluetoothChat을 사용하였으며,

여기서 UUID의 변경이 필요하다. 핸드폰과 핸드폰간의 블루투스 통신과

노트북과 핸드폰 간의 통신에서는 다른 UUID를 사용하기 때문이다.



핸드폰에서 메뉴를 선택하면 커넥할 드라이브를 찾을 수 있도록 되어 있다.

해당 드라이버를 찾아 연결하게 된다.





연결이 되면 서버에서 확인이되며 폰에서도 확인이 가능하다.






드로에서 연결을 종료하게 되면 위와 같은 메시지가 나오며 다시 접속을 기다리게된다.







블루투스 통신을 해본 결과, 절차를 지키는 것이 굉장히 중요하며 연속적인 연결과 접속 해제를 할 경우 
정상적으로 접속되지 않는 경우가 많이 발생하게 된다. 

소스파일첨부







블루투스 통신을 통한 채팅 테스트 영상





블루투스 통신을 통한 화면 제어 테스트 영상





'Programing > C#&.Net' 카테고리의 다른 글

D Day 프로그램  (0) 2016.11.30
계산기 예제  (0) 2016.11.30
speech To Text  (0) 2016.11.30
회원관리 연습  (0) 2016.11.30
.NET 리모팅  (0) 2016.11.30

Interop.SpeechLib.dll




본 프로젝트에서 사용될 음성인식 부분이다.

-음성인식은 Speach엔진을 사용하였으며, Speach엔진을 사용하는 방법이다.

-DLL로 구성하였다.

-참조된 SpeachDLL을 포함하고 있어야한다.

-MS에서 재공하는 SpeechSDK51.exe 를 다운받아야 사용할 수 있다.


public class Speach

    {

        SpeechLib.SpSharedRecoContext objRecoContext = null;

        SpeechLib.ISpeechRecoGrammar grammar = null;

        SpeechLib.ISpeechGrammarRule menuRule = null;

        public event SpeachResultReturn SpeachResultReturnEventHandler = null;

        public string result = string.Empty;

        public string Result

        {

            get

            {

                return result;

            }

        }

        public void StartSpeach()

        {

            objRecoContext = new SpeechLib.SpSharedRecoContext();

            objRecoContext.Hypothesis += new _ISpeechRecoContextEvents_HypothesisEventHandler(objRecoContext_Hypothesis);

 

            objRecoContext.Recognition += new _ISpeechRecoContextEvents_RecognitionEventHandler(objRecoContext_Recognition);

           

            grammar = objRecoContext.CreateGrammar(0);

            menuRule = grammar.Rules.Add("MenuCommands"SpeechRuleAttributes.SRATopLevel | SpeechRuleAttributes.SRADynamic, 1);

            object PropValue = "";

 

            menuRule.InitialState.AddWordTransition(null"End"" "SpeechGrammarWordType.SGLexical, "End"1ref PropValue, 1.0F);

            menuRule.InitialState.AddWordTransition(null"Start"" "SpeechGrammarWordType.SGLexical,"Start"2ref PropValue, 1.0F);

            menuRule.InitialState.AddWordTransition(null"Aircon"" "SpeechGrammarWordType.SGLexical,"Aircon"3ref PropValue, 1.0F);

            menuRule.InitialState.AddWordTransition(null"Audio"" "SpeechGrammarWordType.SGLexical,"Audio"4ref PropValue, 1.0F);

            menuRule.InitialState.AddWordTransition(null"Option"" "SpeechGrammarWordType.SGLexical,"Option"4ref PropValue, 1.0F);

 

            grammar.Rules.Commit();

            grammar.CmdSetRuleState("MenuCommands"SpeechRuleState.SGDSActive);

        }

 

        void objRecoContext_Recognition(int StreamNumber, object StreamPosition, SpeechRecognitionType RecognitionType, ISpeechRecoResult Result)

        {

            string txtReco = string.Empty;

            txtReco = Result.PhraseInfo.GetText(0, -1true);

            switch (txtReco)

            {

                case "End": result = "End"break;

                case "Start": result = "Start"break;

                case "Aircon": result = "Aircon"break;

                case "Audio": result = "Audio"break;

                case "Option": result = "Option"break;

            }

            if (txtReco != null)

            {

                if (SpeachResultReturnEventHandler != null)

                {

                    SpeachResultReturnEventHandler();

                }

            }

        }

 

        void objRecoContext_Hypothesis(int StreamNumber, object StreamPosition, ISpeechRecoResult Result)

        {

            string txtHyp = string.Empty;

            txtHyp = Result.PhraseInfo.GetText(0, -1true);           

        }

    }


 

-사용법

-WinFrom 응용프로그램 이용하여 Test프로그램을 만들어 보았다.

public partial class Form1 : Form

    {

        SpeachDll.Speach myspeach = new SpeachDll.Speach();

        public Form1()

        {

            InitializeComponent();          

        }

 

        private void button1_Click(object sender, EventArgs e)

        { 

            myspeach.StartSpeach();

            myspeach.SpeachResultReturnEventHandler += new SpeachDll.SpeachResultReturn(myspeach_SpeachResultReturnEventHandler);

        }

 

        void myspeach_SpeachResultReturnEventHandler()

        {

            MessageBox.Show(myspeach.Result);

        }

    }


'Programing > C#&.Net' 카테고리의 다른 글

계산기 예제  (0) 2016.11.30
노트북 블루투스 + 안드로이드 폰 연동  (0) 2016.11.30
회원관리 연습  (0) 2016.11.30
.NET 리모팅  (0) 2016.11.30
직렬화(Serializable) 예제  (0) 2016.11.30

종료시 해당 파일을 저장하기 위한 코드

  private void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {
            gd = GlobalData.GetInstance();
            string path = string.Format(@"{0}\cozy.txt", GlobalData.ProgramDir);
            FileStream fs = new FileStream(path, FileMode.Create);           
            BinaryFormatter bf = new BinaryFormatter();            
            bf.Serialize(fs, gd);
            fs.Close();
        } 


폼 시작시 저장된 파일을 불러오기 위한 코드

  private void MainForm_Load(object sender, EventArgs e)

        {
            GlobalData gd2 = GlobalData.GetInstance();
            if (File.Exists("cozy.txt"))
            {
                FileStream fs = File.OpenRead("cozy.txt");
                BinaryFormatter bf = new BinaryFormatter();
                gd2 = bf.Deserialize(fs) as GlobalData;
              
                gd.MemList = gd2.MemList;
                for (int i = 0; i < gd.GetList().Count; i++)
                {
                    listView1.Items.Add(gd.GetList()[i].Name);
                    listView1.Items[i].SubItems.Add(gd.GetList()[i].Id);
                }
                fs.Close();
            }
        }



사진 업로드를 위한코드

  private void button3_Click(object sender, EventArgs e)

        {
            //OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Filter = "Bmp File(*.bmp,*.jpg)|*.bmp;*.jpg";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                GlobalData global = GlobalData.GetInstance();                
               if (!global.IsExist(textName.Text))
               {
                   Bitmap bmp = new Bitmap(Image.FromFile(openFileDialog1.FileName));
                   //bmp.Save(string.Format(@"{0}\{1}.bmp", GlobalData.MembersDir, textName.Text));
                   pictureBox1.Image = bmp;
                   textAddFile.Text = openFileDialog1.FileName;
               }
            }          
        }



사진을 불러오기 위한 코드(회원 추가 버튼이 발생했을때 수행)

                  if (AddMemberEventHandler != null)

            {
                DateTime dt;
                id = textID.Text;
                pw = textPW.Text;
                name = textName.Text;
                age = int.Parse(textAge.Text);
    
                dt = dateTimePicker1.Value;
                
                AddMemberEventHandler(id, pw, name, age,dt);
               
                Bitmap bmp = new Bitmap(Image.FromFile(openFileDialog1.FileName));
                bmp.Save(string.Format(@"{0}\{1},{2}.bmp", GlobalData.MembersDir, textName.Text,i));
                i++;
                this.Close();
                NullChangeEventHandler();                
            }



회원추가 및 메인화면


회원이름을 더블클릭 하였을때 회원정보 출력


저장된 파일과 사진정보



'Programing > C#&.Net' 카테고리의 다른 글

노트북 블루투스 + 안드로이드 폰 연동  (0) 2016.11.30
speech To Text  (0) 2016.11.30
.NET 리모팅  (0) 2016.11.30
직렬화(Serializable) 예제  (0) 2016.11.30
명시적 어셈블리 로딩  (0) 2016.11.30

+ Recent posts