반응형

이전의 Java 포스팅을 이어가야하는데.. 하면서 깜빡깜빡하네요. 조만간 이어가도록 하겠습니다.

여튼 이번엔 프로그래머나 개발자라면 기본적으로 다루게 될 Java API와 관련하여 자신의 Local에서 Socket을 이용한 서버와 클라이언트의 Data를 주고받는 부분을 살펴보려 합니다.


[SocketServer.java]

/**
* Created by 진우 on 2016-07-09.
*/
public class SocketServer {
public static void main(String[] args) {
SocketServer serv = new SocketServer();
serv.startServer();
}

public void startServer() {
ServerSocket sockserv = null;
Socket sockcli = null;

try {
sockserv = new ServerSocket(9629);
while(true) {
System.out.println("Server is waiting for request.");

sockcli = sockserv.accept();
System.out.println("Server Socket is Accepted!");

InputStream stream = sockcli.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String data = null;
StringBuilder receiveData = new StringBuilder();
while((data = in.readLine()) != null) {
receiveData.append(data);
}
System.out.println("Receive Data :"+receiveData);
in.close();
stream.close();
sockcli.close();
if(receiveData.toString().equals("End of TEST")) {
System.out.println("Stop Socket Server!");
break;
}
System.out.println("------");
}
} catch(Exception e) {
e.printStackTrace();
} finally {
if(sockserv != null) {
try {
sockserv.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}


먼저 서버에서는 Socket을 서버, 클라이언트용으로 두 개 만들어줍니다.

그리고 StartServer() 에서 포트를 9629로 하여 로컬에서 실행되도록 합니다.

while(true)문을 이용하여 Client로부터 End of Test 라는 메시지가 올 때까지 계속 실행되도록 합니다.

socket accept를 통해 클라이언트로부터 data를 받아들이고, data가 null일 때까지 계속 while문으로 받아서 receiveData에 append해줍니다.

그리고 다 받아서 while문을 빠져나오면, socket과 stream을 close 해주어 마무리해줍니다.


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

[SocketClient.java]

/**
* Created by 진우 on 2016-07-09.
*/
public class SocketClient {
public static void main(String[] args) {
SocketClient cli = new SocketClient();
cli.sendSocket();
}

public void sendSocket() {
for(int loop = 1; loop <= 5; loop++) {
sendSocketData("Just Test Client - Server (" + loop + ")");
}
sendSocketData("End of TEST");
}

public void sendSocketData(String data) {
Socket sock = null;
try {
System.out.println("Client is Connecting");

sock = new Socket("127.0.0.1", 9629);
System.out.println("Client:Connect status = "+sock.isConnected());
Thread.sleep(1500);
OutputStream stream = sock.getOutputStream();
BufferedOutputStream out = new BufferedOutputStream(stream);
byte[] bytes = data.getBytes();
out.write(bytes);

System.out.println("Client:Send data");
out.close();

} catch(Exception e) {
e.printStackTrace();
} finally {
if(sock != null) {
try {
sock.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
}


Client에서는 for문을 이용하여 서버에 5번 Data를 보내게 됩니다. 그리고 마지막으로 End of Test 라는 메시지를 보내어 서버가 이 메시지를 받았을 때 종료되도록 합니다.

sendSocketData()에서는 Socket을 생성하여 Local서버(127.0.0.1)에 9629포트에 보내도록 하고, Socket의 현재 상태(연결 되어 있는지 - sock.isConnected() 이용) 를 Client에서 출력해줍시다.

간격은 Thread를 이용하여 1.5초(1500mllis)로 하고, OutputStream을 이용하여 서버에 data를 보내줍니다.

그 후, client에서 Send data 메시지를 출력해 준 후, stream을 닫아줍니다.


network통신에서는 try - catch 문을 꼭 이용하여 Exception이 발생 했을 시를 체크해줍시다.



원래 Eclipse를 애용했었는데 요즘은 시대에 맞게 Intellij를 되도록 사용하려 합니다.

아직은 조금 서툰부분도 많습니다만 빨리 적응해야겠습니다.

반응형

WRITTEN BY
SiriusJ

,
반응형

[DoS(도스) 공격이란? 의미. ]

DoS(도스 (Denial of Service) : DoS는 인터넷 상의 특정 자원을 평소처럼 이용할 수 없는 상태를 말합니다. 이러한 서비스 단절은 여러 가지 이유가 있을 수 있는데 보통 네트워크 장애로 인한 제대로 된 서비스를 못하게 됩니다.

DoS공격은 보통 한 두대의 컴퓨터로 타겟 서버의 공략법으로 과다하게 트래픽을 유발하거나, 시스템 마비를 일으켜서 서비스 단절상태로 만들었지만 방어기법(IP Blocking : 과다하게 패킷이 들어오는 특정 IP를 막는 방어기법)으로 처리가 가능해지게 되었습니다.

 DoS는 효과적인 공격방법을 잃게 되고, 이 공격기법을 발전시켜서 나온 것이 Distributed DoS(DDoS) 방법입니다. 여러 곳에서 분산해서 동시다발적으로 집중 공격함으로써 IP Blocking 방어 기법을 무력화 시키는 방법입니다.


[ DDoS 공격이란? 의미. ]

DDoS(디도스(Distributed Denial of Service) 공격 (분산 서비스 공격) : 수 많은 개인 컴퓨터에 악성 코드 또는 해킹툴과 같은 것들을 유포하여 이들의 컴퓨터를 '좀비 PC'로 만들고, 좀비 PC화 된 컴퓨터들을 통해 지정된 특정 서버에 동시에 대량의 트래픽을 유발시켜 서버의 기능이 마비되도록 만드는 공격입니다.


이는 한 사람 혹은 특정 목적을 가진 그룹에 의해 여러 대의 컴퓨터들이 일제히 동작하도록 조종되어 특정 서버 혹은 사이트에 대량의 트래픽을 유발시켜 그 서버 혹은 사이트가 제 기능을 수행할 수 없게 만들기에 붙여진 이름입니다.


이 때, DDoS(디도스) 공격에 이용되어지는 개인 컴퓨터들이 일명 '좀비 PC'라고 불려지게 됩니다.


개인 사용자의 컴퓨터가 '좀비PC' 로 되는 것은 개인 사용자들이 파일을 다운로드 받거나, 유해사이트와 같은 곳에 접속했을 때나 혹은 이메일이나 메신저 등의 경로를 통해 사용자의 컴퓨터에 몰래 악성코드 또는 해킹툴이 심어지게 됨으로써 완성되게 됩니다.


이렇게 악성코드나 해킹툴이 심어진 컴퓨터를 해커가 원격으로 조종하거나 미리 입력된 명령에 의해 사용자의 의지와 상관없이 해당 컴퓨터에서 특정 서버나 사이트로 무차별적인 패킷을 보내게 되는 것입니다.


즉 이렇게 특정 서버나 사이트가 하나하나의 '좀비PC'들로부터 무차별적인 패킷을 받게 되면, 서버 컴퓨터의 시스템이 이를 처리할 수 없을 정도로 시스템에 과부하가 걸리게 됩니다. 이렇게 과부하에 걸리게 되면 컴퓨터가 먹통이 되거나, 사용할 수 없을 정도로 버벅거리게 됩니다.


* 여기서 패킷이란, 네트워크 통신에서는 수신자(Receiver)와 송신자(Sender)가 있습니다. 수신자와 송신자 간에 데이터를 주고 받을 때 전송하기 쉽도록 일정단위로 데이터를 잘라서 보내게 되는데, 이 때 이 잘려지는 데이터 단위를 패킷이라 부르게 됩니다.

즉, 일반 사용자가 어떤 사이트에 접속하기 위해 해당 서버에 페이지 요청을 할 때에도 그 요청 정보는 패킷 단위로 서버에 전달되고, 파일을 다운로드 하거나 업로드 할 때에도 또한 패킷 단위로 데이터전송이 이루어지게 됩니다.


DDoS(디도스) 공격은 일반적인 바이러스(Virus) 해킹(Hacking)과는 달리 공격하는 대상의 컴퓨터에 침투해서 자료를 삭제하거나 훔치거나 하는 것이 아니라, 공격대상에게 대량의 트래픽을 유발시킴으로써 시스템이 과부하에 빠지게 만들고, 정당한 다른 신호들을 받지 못하게 방해하는 작용만 하게 됩니다.

DDoS(디도스) 공격의 문제점은, 공격에 이용된 '좀비PC'들이 악성코드나 해킹툴의 흔적을 감추기 위해 스스로 하드디스크를 손상시켜 사용자의 컴퓨터가 동작 불능 상태가 되어버리게 만든다는 것입니다.

[ DDoS 공격 ] 


[대비책]

프로그래머/개발자 뿐만 아니라 자신의 PC가 좀비PC가 되는 것을 원치않는 PC 사용자라면 항상 자신의 PC를 잘 관리해야합니다. 대비책은 컴퓨터에 지식이 있는 프로그래머/개발자 뿐만 아니라 누구나 쉽게 할 수 있습니다. 단지 귀찮아서, 사소한 것쯤이야 하는 마음에 위험에 노출되는 것이죠.

1 - 자신의 운영체제는 항상 업데이트를 통해 최신 보안 패치를 받아 두도록 합니다.

( * 윈도우 운영체제일 경우 자동업데이트를 설정함으로써 최신 보안패치상태를 유지할 수 있지만, 혹시라도 아니라면 수동으로라도 업데이트를 하여 최신 보안패치를 적용하는것이 좋습니다.)


2 - 인터넷으로 웹 서핑 할 때, 간혹 프로그램을 설치 할 것인지 묻는 창이 뜨는 경우가 있을 것입니다.

이럴 경우, 신뢰할 수 있는 곳의 프로그램이라면 설치에 동의하고, 확실하지 않다면 무조건 설치를 거부하는 것이 좋습니다.

설치를 거부한다고 해서 '예' 또는 '아니오' 중에서 '아니오'를 눌러도 안되고, 둘 중 어느것도 선택하지 말고 창을 강제로 닫아야합니다.!


3 - 컴퓨터에 관한 지식에 자신이 없으면 이메일 확인시에 발신인이 분명치 않거나 모르는 사람이라면 메일을 보지 말고 그냥 삭제하도록 합니다. (중요한 메일 일 경우에는 발신인을 불명확하게 보내지 않았을 것이라 믿읍시다.)


4 - 메신저 프로그램을 사용한다면, 메시지를 통해 특정 URL이나 파일이 첨부되어 올 경우가 있을 것입니다. 이럴 경우에 함부로 클릭하지 말고, 메시지를 보낸 사람이 직접 보냈는지부터 확인해봅시다.

(확실하지 않으면 함부로 클릭하거나 실행하지 맙시다.)


5 - P2P 프로그램이나 서비스를 제공하는 사이트를 이용해 파일을 다운받을 때에는 반드시! 백신과 같은 프로그램을 이용해 검사한 후 사용하도록 합시다.


6 - 외부 침입자로부터 여러분의 시스템이나 파일이 무단으로 사용되지 못하도록 여러분이 사용하는 운영체제의 필요 없는 공유 설정은 모두 해제하고, 꼭 필요한 경우는 공유 권한은 '읽기' 로 해놓고, 사용한 후에는 공유 설정을 모두 해제하도록 합시다.


7 - 백신과 같은 보안 프로그램을 설치하여 항상 여러분의 시스템을 감시하도록 설정해두고, 검사 엔진은 항상 최신버전으로 업데이트를 유지시켜 둡시다..!!


자신의 PC가 좀비 PC가 되지않도록 스스로 잘 관리하는 습관을 들이는 것이 중요합니다.

반응형

WRITTEN BY
SiriusJ

,
반응형

1) 외부에서 본 프로그램의 동작은 변하지 않고, 

2) 프로그램 내부의 구조를 개선하는 것


따라서 debugging 이나 기능 추가와 같은 것은 리팩토링이라고 할 수 없다. 프로그램의 동작이 변하기 때문이다. 

그렇다면 Refactoring 의 목적은 무엇일까? 말했듯이, 디버깅 자체가 Refactoring 은 아니다. 하지만 리팩토링을 통해서 디버깅이 쉬워질 가능성이 있다. 복잡하고 어지러운 코드에서는 버그를 찾기 쉽지 않기 때문이다. 

기능 추가와 관련하여 다음 그림을 참고한다면 리팩토링의 장점을 알 수 있다. 


출처: http://www.hanbit.co.kr/preview/1511/sample_chapter0.pdf

당장은, 자기 생각대로 빨리 아무렇게나 코딩하는 것이 빠르다고 생각할지 모르겠지만, 처음부터 리팩토링을 생각하며 
코딩하는 것이 결국 전체적인 속도로 보았을 때에, 비교할 수 없을 정도의 차이를 낼 것으로 보인다. 리팩토링 없이 어지럽게 코딩을 마친 후 버그를 잡다가, 결국 전체적인 프로그래밍 설계를 모두 수정해야하는 사태까지 나올 수 있지 않을까 생각한다. 그런데 리팩토링을 하며, 보기 쉽고, 깔끔하게 정리하며 코딩을 하다 보면, 중간에 전체적인 설계가 잘못되어서 코드를 뒤집어야 한다고 하는 최악의 사태가 온다 하더라도, 빨리 판단하고 실행에 옮기게 되어 결국 전체적인 프로젝트 기간을 단축 시킬 수 있을 것 같다. 

다음은 언제 리팩토링을 해야하는가에 대한 펌 자료이니 참고하자. 
출처: http://outliers.tistory.com/entry/%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81Refactoring

언제 리팩토링을 해야 하는가?

  • 별도의 시간을 내는것이 아니라, 틈틈히 계속 해야 하는 것이다.
  • 어떤 것을 할 때 비슷한 어떤것을 하게 되면 리팩토링을 한다.(책에서는 3번째 부터 하라고 나와있지만 바로 한다.)
  • 기능을 추가할 때 리팩토링을 해라.
  • 버그를 수정해야 할 때 리팩토링을 하라.
  • 코드 검토(code review)를 할 때 리팩토링을 하라.
    • 읽기 어려운 프로그램은 수정하기 어렵다.
    • 중복된 로직을 가지고 있는 프로그램 수정하기 어렵다.
    • 실행중인 코드를 변경해야 하는 특별한 동작을 요구하는 프로그램은 수정하기 어렵다.
    • 복잡한 조건문이 포함된 프로그램은 수정하기 어렵다.

그러나 리팩토링을 지양해야할 때도 있다. 

언제 리팩토링을 하지 말아야 하는가?

  • 코드를 처음부터 다시 작성해야 할때
  • 마감일에 가까울 때


그렇다면 리팩토링과 디자인패턴 (design pattern) 과는 어떤 관계가 있을까? 

디자인패턴은 목표이고 리팩토링은 방법이라고들 말을 한다. 

다음은 디자인 패턴이 무엇인지 잘 정리되어있는 펌자료이다. 
출처: http://alleysark.tistory.com/entry/Design-pattern-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80

- 디자인 패턴이란?

클래스 구조를 갖는 프로그래밍을 하다보면 클래스간에 구조가 짜여지고 다양한 방법으로 객체가 생성되며 관계에 따라 여러가지 형태의 행동들이 나타난다. 그런데 기초 설계가 제대로 되어있지 않은 상태로 프로그래밍이 시작된다면 얼마 못가 클래스 관계가 꼬일대로 꼬여 누더기 진흙탕 코드덩어리로 변하게된다. 엄청나게 뛰어난 사람이어서 초기 요구에 맞춰 잘 짜여진 클래스관계를 만든다 해도 요구 사항이 바뀌게되면 쉽게 대응하지 못한다. 이미 갈 때 까지 간 코드를 뒤엎는건 그만큼 큰 비용을 감수해야하는 행동이다.

 

그런데 Object oriented programming은 이게 아니지 않은가? 분명 클래스 구조의 프로그래밍을 했는데도 프로젝트가 진행되다보면 데이터의 은닉과 캡슐화, 코드의 재사용성과 확장성 등은 누더기 코드에 가려 보이지 않는다. 제대로된 OOP를 하지 못했다는 이야기이다. 그렇다면 제대로된 OOP란 무엇을 말하는것인지 의문이 생긴다. 많은 사람들이 이에대해 고민했고 프로그램의 목적이 어떻든간에 프로그램안에 클래스들이 갖는 구조에는 일정한 '형태' 혹은 '패턴' 이 존재한다는 것을 인지하기 시작했다. 이를 바탕으로 클래스간의 관계, 클래스간의 행동양식을 분류하고 각각에 대해 객체지향적인 설계를 따르는 노하우들이 차곡차곡 정리되어 객체지향적으로 합당한 클래스 설계 형태를 정립하기 시작했고 이를 클래스 디자인 패턴 이라 이름붙이게 되었다.

 

클래스 디자인 패턴은 "'이러한 상황' 이라면 '이러한 형태의 클래스 디자인'을 하는게 대게 좋더라" 라고 말해주는것이다. 프로젝트 규모가 커지고 협업 인원이 많아질수록 이러한 기준은 일을 효율적으로 처리할 수 있게 만들어준다. 하지만 주의해야한다. 표준화된 작업은 여러가지 상황을 고려하며 만들어지기 때문에 대체로 효율성이 떨어지기 마련이다. 또한 패턴간의 관계를 생각하지 못하면 설계를 복잡하게 만드는 요소가 되어버린다. 그렇기 때문에 클래스 설계자는 분류된 디자인 패턴의 사용 목적, 장단점, 강점과 약점에 대한 충분한 이해와 패턴간의 융합에 발생할 수 있는 문제점들을 확실히 예상할 수 있어야 하며 이를 바탕으로 디자인 패턴을 적용해야한다. 무분별한 패턴의 남용은 오히려 프로그램을 망치게된다.


디자인 패턴이 리팩토링을 위한 방법이라고 말했듯이, 디자인 패턴들이 분명 유용하긴 하나, 디자인패턴이 너무 강조될 경우, 오히려 더 코드가 지저분해질 염려도 된다고 퍼온 자료의 저자는 말한다. 결국, 목적이 더 좋은 설계가 되어야지, 디자인 패턴 자체가 되어서는 안된다는 뜻으로 받아드리려고 한다. 


다음과 같은 펌자료 저자의 의견도 함께 첨부한다. 


만약 무분별 하게 디자인 패턴이 사용되고 패턴들이(클래스들이) 유기적으로 결합되지 못한다면 클래스 설계에 있어서 디자인 패턴은 필요악 되어버린다. 설계자는 패턴에 목메기보다는 설계원칙을 잘 생각하면서 이를 받쳐줄 검증된 방법론으로서 디자인 패턴을 고려하여야 할 것이다.

 

또 한가지는 프로그램의 구동 환경에 있다. PC 어플리케이션이라면 디자인패턴이 가져오는 퍼포먼스에 대한 결점은 큰 문제가 되지 않을 것이다. 하지만 안드로이드 같은 모바일 환경이나 임베디드 환경이라면 디자인패턴은 사치품에 지나지 않는다.

 

마지막으로 프로그램의 구동 목적이 고려되어야 한다. 구동에 큰 설계가 필요하지 않거나 명확한 클래스구조를 갖고 코드의 변경을 고려하지 않아도 된다면 디자인패턴은 쓸데없는 비용을 늘리는 요소가 된다. 그리고 게임프로그램, 서버프로그램과 같은 고성능의 실행환경을 요구하는 프로그램이라면 퍼포먼스를 낮추는 디자인패턴은 필요성에 대해 신중에 신중을 기할 필요가 있다.



[전체 출처 : http://egloos.zum.com/johnny1984/v/9072065 ]

반응형

WRITTEN BY
SiriusJ

,
반응형

날씨 API는 많이 지원해주고 있습니다.

기상청API나 기타 다른 API들도 있지만 그 중에서도 저는 이번에 Openweather라는 날씨 API를 이용해보려 합니다.

(저는 Node.js를 이용한 서버에서 JSON 형식의 데이터로 파싱해오도록 하겠습니다.)


먼저 http://www.openweathermap.org/ 으로 접속해봅시다.


상단 메뉴에서 API를 클릭하면 아래와 같이 보실 수 있습니다.

먼저, API Key를 클릭하여 해당 페이지로 이동하고, Sign up을 하여 API KEY를 얻어줍시다.

(API를 사용하기 위해 얻어진 API KEY는 꼭 기억해주셔야 합니다!)


이후에 Current weather data 의 API doc을 클릭하여 문서를 참조하면, API를 이용하는 부분에 대한 설명을 확인할 수 있습니다. API를 이용하는 중요한 정보들이 대부분 이곳에 있으므로 자주 참조하게 될 것입니다.


만약, API KEY를 얻었다면, 아래에서 APPID=  다음에 받으신 API KEY를 그대로 넣어서 브라우저에서 접속해보면, 현재 서울의 기상정보를 JSON형식의 데이터로 바로 확인할 수 있습니다.

http://api.openweathermap.org/data/2.5/weather?q=Seoul&mode=json&units=metric&APPID=(당신의KEY를넣어주세요.)

(크롬 브라우저에서의 URL을 이용한 날씨정보 확인 - 참고)

여기까지, 만약 브라우저에서 해당 url로 접속했을 때 다음과 같이 데이터가 보이지 않는다면 API KEY가 잘못되었을 확률이 높으므로 다시한번 확인해줍시다!


만약, 잘 확인이 되었다면, 이제 자신의 서버에서 직접 서버에 요청을 보내어 위와 같은 데이터를 가져와야 합니다.

아래 코드에서 URL에 APPID에 자신의 APPKEY만 수정해서 넣어주시면 됩니다.

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

[testServer.js]

var http = require('http');

var express = require('express');


var app = express();

var server = http.createServer(app);


app.use(express.static(__dirname + "/index"));


app.get('/', function(req, res, err) {

res.send(200, "Success");

});


//(Temp variable), for Weather Information

var cityname, citylon, citylat, cityweather, weatherid, weathermain, citytemp, cityhumi, citytemp_min, citytemp_max, citywind, cityclouds;

//var weatherArr = new Array();            아래에서 변수에 저장하는 대신 배열을 이용하셔도 됩니다.


//(Temp variable2), for Today weather Information

var citytime9, citytemp9, cityhumi9, citymain9, cityid9;

var citytime12, citytemp12, cityhumi12, citymain12, cityid12;

var citytime15, citytemp15, cityhumi15, citymain15, cityid15;

var citytime18, citytemp18, cityhumi18, citymain18, cityid18;

var citytime21, citytemp21, cityhumi21, citymain21, cityid21;


//현재시간에 맞는 서울의 날씨정보를 얻어오는 function입니다.

function currentInfo() {

var urlCurr = 'http://api.openweathermap.org/data/2.5/weather?q=Seoul&mode=json&units=metric&APPID=당신의API키를넣어주세요.';


http.get(urlCurr, function(res) {

var body = '';

res.on('data', function(chunk) {

body += chunk.toString();

});


res.on('end', function() {

try {

var fbResponse = JSON.parse(body);    

//JSON형식으로 추출하여 fbResponse에 담아주고, 아래에서 각각의 변수들에 해당 데이터를 저장해 줍니다.


cityname = fbResponse.name;        //도시 이름

citylon = fbResponse.coord.lon;      //도시의 좌표(경도,위도)

citylat = fbResponse.coord.lat;

weatherid = fbResponse.weather[0].id;

weathermain = fbResponse.weather[0].main;

citytemp = fbResponse.main.temp;

cityhumi = fbResponse.main.humidity;

citytemp_min = fbResponse.main.temp_min;

citytemp_max = fbResponse.main.temp_max;

citywind = fbResponse.wind.speed;

cityclouds = fbResponse.clouds.all;

//아래에서 로그를 콘솔에 찍어봄으로써 데이터가 제대로 추출되었는지 확인해봅니다.

console.log("cityname=", cityname);

console.log("weatherid=", weatherid);

console.log("weathermain=", weathermain);

console.log("citytemp=", citytemp);

} catch (e) {

console.log(e);

/* 가끔씩, 한번에 못 받아올때가 있습니다. (아마 서버쪽의 오류인듯 싶습니다.) 그래서 만약 못받아 올 때를 대비하여 try-catch구문을 이용하여 catch에서 currentInfo()를 한번 더 선언해줌으로써 오류가 났을 때에는 다시 한번 요청을 해서 받아오게 됩니다. */

currentInfo();

}

});

res.on('error', function(e) {

console.log("Got an error: ", e);

});

});

}

//Active Once. (First) - 서버를 실행할 때, currentInfo()를 불러주어 아래에서 API를 처음 call하게 됩니다.

currentInfo();

//After, repeat Active (After), - (period 1Hour, for update) - 이후에, 1시간 간격으로 Interval을 통하여 지속적으로 실행해줍니다.

var curi = setInterval(currentInfo, 3600000);



/*아래의 todayInfo()는 현재 시간에 따른 날씨정보 뿐만 아니라 오늘의 날씨정보를 얻기 위하여 추가로 작성해보았습니다.*/

// request for today(forecast) -  위의 currentInfo()와 같은 내용이므로 자세한 설명은 생략하도록 하겠습니다.

function todayInfo() {

var urltoday = 'http://api.openweathermap.org/data/2.5/forecast?q=Seoul&mode=json&units=metric&APPID=당신의API키를넣어주세요.';

http.get(urltoday, function(res) {

var body2 = '';

res.on('data', function(chunk2) {

body2 += chunk2.toString();

});


res.on('end', function() {

try {

var fbResponse2 = JSON.parse(body2);


citytemp9 = fbResponse2.list[0].main.temp;

cityhumi9 = fbResponse2.list[0].main.humidity;

cityid9 = fbResponse2.list[0].weather[0].id;

citymain9 = fbResponse2.list[0].weather[0].main;

citytemp12 = fbResponse2.list[1].main.temp;

cityhumi12 = fbResponse2.list[1].main.humidity;

cityid12 = fbResponse2.list[1].weather[0].id;

citymain12 = fbResponse2.list[1].weather[0].main;


citytemp15 = fbResponse2.list[2].main.temp;

cityhumi15 = fbResponse2.list[2].main.humidity;

cityid15 = fbResponse2.list[2].weather[0].id;

citymain15 = fbResponse2.list[2].weather[0].main;


citytemp18 = fbResponse2.list[3].main.temp;

cityhumi18 = fbResponse2.list[3].main.humidity;

cityid18 = fbResponse2.list[3].weather[0].id;

citymain18 = fbResponse2.list[3].weather[0].main;


citytemp21 = fbResponse2.list[4].main.temp;

cityhumi21 = fbResponse2.list[4].main.humidity;

cityid21 = fbResponse2.list[4].weather[0].id;

citymain21 = fbResponse2.list[4].weather[0].main;

console.log("citymain in 9(Morning)=", citymain9);

console.log("citymain in 21(Evening)=", citymain9);

} catch (e) {

console.log(e);

todayInfo();

}

});

res.on('error', function(e) {

console.log("Got an error: ", e);

});

});

}

todayInfo();

var todayI = setInterval(todayInfo, 86400000); //86400sec = 1 day,(period 1day, for update)


server.listen(8888, function(req, res) {

console.log("server running on 8888.");

});


///////////////////////////////////////////////////////////////////////////////////////////////////////////////

이해를 돕기위하여 변수를 무지막지하게 선언했습니다...

변수들 대신에 배열을 만들어서 원하는 데이터를 추출하셔도 됩니다.

ex) var weatherArr[];

와 같이 선언 후, 배열에 파싱한 값을 넣어주셔도 됩니다.


이상으로, GET방식으로 서버에 요청하여 JSON 형식의 데이터를 받아오는 모습이었습니다.


위 코드를 작성하고 실행시키면, 아래와 같이 데이터가 콘솔에 찍히는 것을 확인 할 수 있습니다.

(워낙에 설명이 빈약해서.. 참고 설명으로 cityname은 url에서 요청한 도시에 대한 이름이, weatherid는 Open weather API에서 지정한 날씨Code가, weathermain은 날씨의 정보가, citytemp는 도시의 온도 정보 입니다.!)


보다 구체적인 데이터들을 확인하고, 파싱하고 싶다면 문서를 참조하시는걸 추천드립니다! 또한 서울 뿐만이 아니라 URL에서 Seoul 대신 다른 도시로 바꿔주어 해당 도시에 대한 정보를 얻을 수 있습니다. Open weather에서 제공하는 도시의 목록은 http://www.openweathermap.org/current 부분을 열심히 뒤져보시면 어딘가에 도시 Sample들에 대한 파일이 있을겁니다. 받으셔서 도시들 목록을 확인하시면 됩니다. (우리나라 뿐만 아니라 세계 각국의 도시들도 무지 많습니다.)

http://bulk.openweathermap.org/sample/ )

반응형

'Programming > Node.js' 카테고리의 다른 글

Node.js 로 서버 구축  (0) 2016.06.26

WRITTEN BY
SiriusJ

,
반응형

[MainActivity.java]

public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}


[activity_main.xml]

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<TextView
android:id="@+id/label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Type here:"/>

<EditText
android:id="@+id/entry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background"
android:textColor="#000"
android:layout_below="@id/label"/>

<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dip"
android:text="OK" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/ok"
android:layout_alignTop="@id/ok"
android:text="Cancel" />

</RelativeLayout>


반응형

WRITTEN BY
SiriusJ

,
반응형

Node.js 를 이용하여 서버를 간단하게 생성해보도록 하겠습니다.


[testServer.js]

var http = require('http');

var express = require('express');


var app = express();

var server = http.createServer(app);


app.use(express.static(__dirname + "/index"));


app.get('/', function(req, res, err) {

res.send(200, "Success");

});


server.listen(8888, function(req, res) {

console.log("server running on 8888.");

});

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

[index.html]

<!DOCTYPE html>

<html>

<head>

<meta charset="EUC-KR">

<title>Test Page</title>

</head>

<body>

<h1>Hello, It is Test Page!</h1>

</body>

</html>

반응형

WRITTEN BY
SiriusJ

,
반응형

본 포스팅에서 네이버 음성인식API를 이용하는데에 필요한 코드는

MainActivity.java, NaverTalkActivity.java, NaverRecognizer.java, AudioWriterPCM.java, activity_main.xml, activity_talk.xml 입니다.

(포스팅에서 다루는 저의 경우이니, 사용하시는 분에 따라서 변경될 수 있겠습니다.)

///////////////////////////////////////////////////////////////////////////////////////////////////

지난 포스팅에 이어 이제 NaverTalkActivity 를 만들어줄 차례입니다. 군데군데 수정만 해주시면 될것입니다.


이전에 다운받았던 SDK로 이동하여, 

naverspeech-sdk-android-master\naverspeech-sdk-android-master\sample\NaverspeechClient-android-studio\app\src\main\java\com\naver\naverspeech\client 로 이동하면 아래와 같이 3가지 소스가 있습니다.

( MainActivity의 내용을 조금 수정하여 NaverTalkActivity를 만들어 줄 것입니다. 이 부분은 아래에서! )

우선, utils의 내용은 같으므로, 본인의 안드로이드 스튜디오에서 utils 패키지를 만들어 준 후, AudioWriterPCM.java 를 그대로 옮겨줍니다. 패키지 이름에 계속 신경써줍시다.

그리고, NaverRecognizer.java 또한 같으므로, 그대로 본인의 프로젝트로 옮겨줍니다.

지난 포스팅에서 저는 naverTalk라는 패키지를 하나 만들어서 그 안에 넣어주었으므로 그렇게 따라하시면 됩니다.

(만약, MainActivity와 같은 패키지에 하셔도 상관없지만, 이전 포스팅에서 Manifest에서 activity의 경로는 수정해주셔야 됩니다.)

naverTalk라는 패키지에 이제 NaverTalkActivity.java 를 생성해줍시다.


/////////////////////////////////////////////////////////////////////////////////

[NaverTalkActivity.java]

import java.lang.ref.WeakReference;

import com.naver.naverspeech.client.utils.AudioWriterPCM;

import com.naver.speech.clientapi.SpeechConfig;

//다른 import 또한 추가해주시면 됩니다.


public class MainActivity extends Activity {

private static final String CLIENT_ID = "Your Client ID"; // "내 애플리케이션"에서 Client ID를 확인해서 이곳에 적어주세요.

private static final SpeechConfig SPEECH_CONFIG = SpeechConfig.OPENAPI_KR; // or SpeechConfig.OPENAPI_EN


private RecognitionHandler handler;

private NaverRecognizer naverRecognizer;

private TextView txtResult;

private Button btnStart;

private String mResult;

private AudioWriterPCM writer;

private boolean isRunning;


// Handle speech recognition Messages.

private void handleMessage(Message msg) {

switch (msg.what) {

case R.id.clientReady:

// Now an user can speak.

txtResult.setText("Connected");

writer = new AudioWriterPCM(

Environment.getExternalStorageDirectory().getAbsolutePath() + "/NaverSpeechTest");

writer.open("Test");

break;


case R.id.audioRecording:

writer.write((short[]) msg.obj);

break;


case R.id.partialResult:

// Extract obj property typed with String.

mResult = (String) (msg.obj);

txtResult.setText(mResult);

break;


case R.id.finalResult:

// Extract obj property typed with String array.

// The first element is recognition result for speech.

String[] results = (String[]) msg.obj;

mResult = results[0];

txtResult.setText(mResult);

break;


case R.id.recognitionError:

if (writer != null) {

writer.close();

}


mResult = "Error code : " + msg.obj.toString();

txtResult.setText(mResult);

btnStart.setText(R.string.str_start);

btnStart.setEnabled(true);

isRunning = false;

break;


case R.id.clientInactive:

if (writer != null) {

writer.close();

}


btnStart.setText(R.string.str_start);

btnStart.setEnabled(true);

isRunning = false;

break;

}

}


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_talk);


txtResult = (TextView) findViewById(R.id.txt_result);

btnStart = (Button) findViewById(R.id.btn_start);


handler = new RecognitionHandler(this);

naverRecognizer = new NaverRecognizer(this, handler, CLIENT_ID, SPEECH_CONFIG);


btnStart.setOnClickListener(new OnClickListener() {


@Override

public void onClick(View v) {

if (!isRunning) {

// Start button is pushed when SpeechRecognizer's state is inactive.

// Run SpeechRecongizer by calling recognize().

mResult = "";

txtResult.setText("Connecting...");

btnStart.setText(R.string.str_listening);

isRunning = true;


naverRecognizer.recognize();

} else {

// This flow is occurred by pushing start button again

// when SpeechRecognizer is running.

// Because it means that a user wants to cancel speech

// recognition commonly, so call stop().

btnStart.setEnabled(false);


naverRecognizer.getSpeechRecognizer().stop();

}

}

});

}


@Override

protected void onResume() {

super.onResume();

// initialize() must be called on resume time.

naverRecognizer.getSpeechRecognizer().initialize();


mResult = "";

txtResult.setText("");

btnStart.setText(R.string.str_start);

btnStart.setEnabled(true);

}


@Override

protected void onPause() {

super.onPause();

// release() must be called on pause time.

naverRecognizer.getSpeechRecognizer().stopImmediately();

naverRecognizer.getSpeechRecognizer().release();

isRunning = false;

}


// Declare handler for handling SpeechRecognizer thread's Messages.

static class RecognitionHandler extends Handler {

private final WeakReference<MainActivity> mActivity;


RecognitionHandler(MainActivity activity) {

mActivity = new WeakReference<MainActivity>(activity);

}


@Override

public void handleMessage(Message msg) {

MainActivity activity = mActivity.get();

if (activity != null) {

activity.handleMessage(msg);

}

}

}

}


/////////////////////////////////////////////////////////////////////////////////

위에서, NaverTalkActivity.java를 만들어주었다면. 이제 onCreate에서 해당 레이아웃을 꾸며주어 버튼을 클릭했을 때에, 음성인식을 받도록 기능을 구현하게 합니다.

activity_talk.xml의 소스는 간단합니다. 클릭할 버튼 하나와, 음성인식한 텍스트를 보여줄 TextView 하나만 있으면 됩니다.


[activity_talk.xml]

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context="com.naver.recognition.client.MainActivity" >


    <Button

        android:id="@+id/btn_start"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_centerHorizontal="true"

        android:text="@string/str_start" />


    <TextView

        android:id="@+id/txt_result"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_below="@id/btn_start"

        android:layout_centerHorizontal="true"

        android:singleLine="false" />

</LinearLayout>



/////////////////////////////////////////////////////////////////////////////////

그리고, 이제 본 애플리케이션의 MainActivity와 activity_main.xml 을 꾸며봅시다!

MainActivity에서 임의의 버튼을 클릭했을 때, NaverTalkActivity로 넘어가도록 할 것입니다.


[activity_main.xml]

기본으로 생성되어져 있는 레이아웃 안에 button만 하나 추가해줍시다.

<Button

                android:id="@+id/btn_voice"

                android:drawableLeft="@android:drawable/ic_btn_speak_now"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_gravity="center"

                android:gravity="center"

                android:textSize="10dp"

                android:text="음성 제어">

</Button>

/////////////////////////////////////////////////////////////////////////////////

[MainActivity.java]

public class MainActivity extends Activity {

private Button voiceBtn;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

voiceBtn = (Button)findViewById(R.id.btn_voice);


voiceBtn.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                Intent intent = new Intent(MainActivity.this, NaverTalkActivity.class);

                startActivity(intent);

            }

        });

}

}


이와 같이 MainActivity.java 를 구성하게 되면 마무리 되어집니다.

간단하게 보이고자 레이아웃을 매우 간단하게 꾸몄으니, 차후 레이아웃 디자인은 각자 예쁘게 꾸미시면 되겠습니다.

사실 네이버 음성인식API에 대한 부분은 워낙 코드도 간단하고 쉬운데다 가이드도 이해하기 쉽게 되어있어서 그대로 따라하셔도 초보자라도 30분~1시간이면 바로 테스트해볼 수 있으실 겁니다.

반응형

WRITTEN BY
SiriusJ

,
반응형

오늘은 네이버에서 제공하는 음성인식 API를 이용해보도록 하겠습니다.

아직은 Beta버전이지만 인식은 무리없이 잘 되는 것 같습니다.


자세한 API이용 설명은 개발가이드에서 제공해주는 https://developers.naver.com/docs/labs/vrecog 를 참고하셔도 금방 할 수 있으실 것입니다.


먼저 https://developers.naver.com/products/vrecog 에 네이버 개발자 센터에서 음성인식(Beta)를 선택하여 네이버에서 제공하는 음성인식API를 이용해봅시다. 

현재는 한국어와 영어를 제공해주고 있으며, 하루에 1000개까지 처리가 가능하다고 합니다.

-> 화면에서 오픈 API이용 신청을 클릭합니다.


애플리케이션 이름을 자유롭게 적어주시고, 카테고리를 설정하신 후, 음성인식API를 사용하기 위해 비로그인 오픈API 를 선택합니다. 

또한 다른 API(지도, 검색, 음성합성 등) 를 사용하고 싶다면, 추가적으로 선택해주시면 됩니다.


저는 안드로이드 스튜디오를 이용하여 애플리케이션을 제작 후, 네이버음성인식을 테스트해보고자 합니다.

따라서 안드로이드 스튜디오에서 처음 프로젝트를 만들 때, 입력한 패키지 이름을 이곳에 적어주시면 됩니다.

** 반드시 본인의 애플리케이션 패키지 이름과 동일하게 해주어야 합니다. ** - 패키지이름정도는 기억해줍시다~

다음으로 동의에 체크해 준 후, 등록하기를 눌러줍니다.


화면처럼, Client ID와 Client Secret 키가 생성된 것을 확인할 수 있습니다. 기억해주세요.


이제, SDK를 다운받아야 합니다. https://github.com/naver/naverspeech-sdk-android 이곳에 들어가시면 아래와 같은 화면에서, 초록색버튼 Clone or Download 를 클릭합시다.

Download ZIP 을 선택하여 코드를 다운받고, 압축을 풀어줍니다.


해당 폴더에 들어가서 sample로 이동하시면 위 화면으로 개발툴이 android-studio와 eclipse 로 나뉩니다. 

저는 Android Studio를 이용하기 때문에 해당 디렉토리로 이동합니다.

이동하셔서 바로 아래의 build.gradle 코드를 (본인의 Android Studio 툴 내에 있는 build.gradle)에 추가해줍니다.


다음으로 app 디렉토리로 이동하여 build.gradle에 있는 아래 코드를 (본인의 Android studio툴 내에서 기존에 존재하는 app-> build.gradle 파일에다가) 중복되는 부분을 제외한 나머지 코드만 추가해주면 됩니다.


그리고, 현 디렉토리(\naverspeech-sdk-android-master\naverspeech-sdk-android-master\sample\NaverspeechClient-android-studio\app) 에 build.gradle 외에 libs 라는 폴더도 있을 것입니다.

그대로 자신의 안드로이드 스튜디오에서 생성한 프로젝트의 똑같은 디렉토리에 그대로 폴더 자체를 복사하여 붙여넣어 줍니다. (libs에는 jar 파일이 들어있습니다.)


위까지 진행 하셨으면 이제 src->main 폴더로 이동하여 jniLibs 라는 폴더 또한 자신의 프로젝트의 해당 디렉토리에 복붙해줍니다.


//////////////////////////////////

이제는 코드에서 처리하도록 할 차례입니다. 먼저 Manifest에서 아래와 같이 작성해주면 됩니다. package=" " 에는 위에서 네이버 개발자센터에서 음성인식API를 등록할 때 설정해주었던 패키지 이름을 적어주시면 됩니다. 자신의 프로젝트 패키지이름과 같을 것입니다.

그리고 4개 permission을 추가해주면 됩니다.

[AndroidManifest.xml]

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="당신의 패키지 이름을 적어주세요!">
<!-- Naver Talk 부분 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


그리고 Activity를 하나 생성해야 하므로 activity 또한 추가해줍니다. (저는 안드로이드 스튜디오 내에서 naverTalk라는 패키지를 만들어서 그 안에 NaverTalkActivity 의 이름으로 만들어주었습니다. )

<!-- Naver Talk -->
<activity android:name=".naverTalk.NaverTalkActivity" />


다음 포스팅에서는 본격적으로 소스들을 수정해주는 부분을 살펴보도록 하겠습니다.

반응형

WRITTEN BY
SiriusJ

,