22
6. 네네네네네 네네네

6. 네트워크와 서비스

  • Upload
    everly

  • View
    113

  • Download
    0

Embed Size (px)

DESCRIPTION

6. 네트워크와 서비스. 네트워크 (1/4). 사용자는 API 들과 네트워크 프로토콜들을 사용함으로써 하위 계층에서 데이터를 전달하는 방법 , 데이터의 신뢰성 등에 대한 걱정 없이 하위 레벨인 애플리케이션 쪽에만 집중할 수 있음. 노드 (Node) : 네트워크란 특정 주소를 가진 기기들이 서로 연결되어 데이터 송수신이 가능한 것을 말함 . 특정 주소를 가진 기기들을 ‘ 노드 ’ 라 함. 네트워크 (2/4). 레이어와 프로토콜 - 프로토콜 : 통신을 위한 규약 및 방법들을 사전에 정의한 것 - PowerPoint PPT Presentation

Citation preview

6. 네트워크와 서비스

Unlocking Android

네트워크 (1/4)

2

사용자는 API 들과 네트워크 프로토콜들을 사용함으로써

하위 계층에서 데이터를 전달하는 방법 , 데이터의 신뢰성

등에 대한 걱정 없이 하위 레벨인 애플리케이션 쪽에만 집중할

수 있음

노드 (Node)

: 네트워크란 특정 주소를 가진 기기들이 서로 연결되어 데이터

송수신이 가능한 것을 말함 . 특정 주소를 가진 기기들을 ‘노드’라 함

Unlocking Android

네트워크 (2/4)

3

레이어와 프로토콜

- 프로토콜 : 통신을 위한 규약 및 방법들을 사전에 정의한 것

- 레이어 : 네트워크 프로토콜 스택의 각 부분을 추상화한 것

- Link Layer : 물리적인 장치와 주소를 묶어주는 역할

ARP/RARP 등과 같은 물리 주소 변환 프로토콜들을 포함

- Internet Layer : 주소변환과 데이터 구성을 담당

IP 의 여러 버전과 ping 프로토콜 , ICMP 등이 있음

- Transport Layer : 실제 데이터 전송 . HTTP, FTP, SMTP, IMAP,

POP, DNS,

SSH, SOAP 등의 등용 레벨 프로토콜들을 포함

Unlocking Android

네트워크 (3/4)

4

IP 레이어 : IP 주소를 할당하고 데이터를 전송 단위인 패킷

(Packet) 으로 나누어 전송하는 일을 담당하는데 패킷을 데이터그램

(Datagram) 으로 표현 . 헤더정보 등을 포함하여 한 번에 보낼 수

있는 데이터의 크기 (MTU) 등을 정의

- IP 주소 : 각 패킷의 발신지와 송신지를 알려줌

- 32bit IP 주소는 IPv4 로써 네 개의 섹션으로 나누어 10 진수로 표현

- ‘127‘ 로 시작 : 항상 사용하는 시스템의 루프백 / 로컬주소 나타냄

- ‘10/192’ : 라우팅이 불가능한 주소 . 같은 로컬 네트워크 세그먼트 안에

있는 기기들끼리는 통신할 수 있지만 외부 네트워크에

존재하는 기가들과는 불가능

- IP 네트워크에서의 패킷 라우팅 작업은 라우터에 의해서 결정됨

Unlocking Android

네트워크 (4/4)

5

TCP 와 UDP

- TCP : 여분의 데이터를 추가하여 패킷들의 순서를 처리하고

패킷이

정확히 도착했을 경우 ACK(acknowledgement) 를 통해

정확하게 도착했는지 확인하므로 데이터 전송의 신뢰성을

기대할 수 있음 .

- UDP : 순서대로 데이터 패킷을 보내거나 ACK 를 받는 부분이

없어

단순히 데이터 전송만 할 뿐 상대방에게 제대로

전달되었는지에 대해서는 책임지지 않음 .애플리케이션 레이어 프로토콜

: TCP/UDP 를 사용하는 트랜스포트 레이어에서 패킷이 전달되면

애플리케이션이 이 내용을 처리함 .

Unlocking Android

클라이언트와 서버

6

데이터는 하나의 통일된 형태로 중앙 서버에 저장되고 ,

클라이언트는 데이터를 검색하거나 데이터를 이용한 작업을

하기 위해 HTTP 와 같은 프로토콜을 사용하여 서버에 접속함

다양한 목적으로 하나의 IP 주소를 사용하는 서버에 동시에

접속하는 많은 클라이언트를 처리하기 위해 포트 사용 .

- Well known Ports : 0 ~ 1023

- Registered Ports : 1024 ~ 49151

- Dynamic/Private Ports : 49152 ~ 65535

Unlocking Android

서버 소켓을 이용한 통신

7

서버 소켓 : 특정 IP 주소와 포트에 대해 데이터를 쓰거나 읽을 수

있는 스트림을 의미

소켓을 사용함으로써 데이터의 형태나 패킷 크기 등의 걱정없이

데이터를 전송할 수 있게 해주며 네트워크의 추상화를 통하여

프로그래머의 수고를 덜어줌

소켓을 사용한다는 것은 오늘날 시스템에서 사용하는 POSIX

표준을 따른다는 것을 의미하므로 소켓과 관련된 모든 작업을 파일

I/O 형태로 처리해야 함

Unlocking Android

소켓 사용 예제 (1/2)

8

public final class EchoServer extends Thread { private static final int PORT = 8889; private EchoServer() {} public static void main(String args[]) { EchoServer echoServer = new EchoServer(); if (echoServer != null) { echoServer.start();

} } public void run() { // 서버의 시작 부분

try { ServerSocket server = new ServerSocket(PORT, 1); // java.net.ServerSocket 사용

while (true) { Socket client = server.accept(); // 각 클라이언트를 위한 java.net.ServerSocket 사용

System.out.println(“Client connected”); while (true) { BufferedReader reader =

new BufferedReader(new InputStreamReader(client.getInputStream())); // BufferedReader 로 입력된 내용

읽어오기 System.out.println(“Read from client”);

지정된 포트를 감시

각 클라이언트는 소켓을 구현

Unlocking Android

소켓 사용 예제 (2/2)

9

String textLine = reader.readLine() + “\n”; if (textLine.equalsIgnoreCase(“EXIT/n”)) { // “EXIT” 를

입력받으면 루프종료 System.out.println(“EXIT invoked, closing client”);

break; } // BufferedWriter 를 사용하여 에코 전송

BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(client.getOutputStream())); System.out.println(“Echo input to client”); writer.write(“ECHO from server: “ + textLine, 0, textLine.length() + 18); writer.flush(); } client.close(); } } catch (IOException e) { System.err.println(e); } }}

입력한 내용이 ‘ EXIT’ 가 아닌 경우 서버는 수신된 데이터를 클라이언트의 OutputStream 에 뿌려줌

Unlocking Android

안드로이드 클라이언트의 에코 서버 호출 (1/2)

10

/* 패키지 명 및 import 구분 생략 */public class SimpleSocket extends Activity {

/* 뷰 변수 선언 부분 생략 */ @Override public void onCreate(final Bundle icicle) { super.onCreate(icicle); this.setContentView(R.layout.simple_socket);

/* 뷰 확장 부분 생략 */ this.socketButton.setOnClickListener(new OnClickListener() { public void onClick(final View v) { socketOutput.setText(""); String output = callSocket(ipAddress.getText(). toString(), port.getText().toString(), socketInput.getText().toString()); socketOutput.setText(output); // 텍스트뷰에 출력될 내용 설정 } }); } private String callSocket(final String ip, final String port, final String socketData) { Socket socket = null; BufferedWriter writer = null; BufferedReader reader = null; String output = null; try { socket = new Socket(ip, Integer.parseInt(port)); // 클라이언트측의 소켓 생성

callSocket 메서드 사용

Unlocking Android

안드로이드 클라이언트의 에코 서버 호출 (2/2)

11

writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String input = socketData; writer.write(input + "\n", 0, input.length() + 1); writer.flush(); output = reader.readLine(); // 소켓의 출력 데이터 읽기 Log.d(Constants.LOGTAG, " " + SimpleSocket.CLASSTAG + " output - " + output); writer.write("EXIT\n", 0, 5); writer.flush(); } catch (IOException e) { Log.e(Constants.LOGTAG, " " + SimpleSocket.CLASSTAG + " IOException calling socket", e); } finally { try { writer.close(); } catch (IOException e) { } try { reader.close(); } catch (IOException e) { } try { socket.close(); } catch (IOException e) { } } return output; }; }

출력을 위한 BufferedReader 설정

입력을 위한 BufferedWriter 설정소켓에 내용 쓰기

Unlocking Android

HTTP 사용하기

12

데이터 전송이 가능한 서버 프로그램이 이미 존재하고 그것을 사용할

수 있다면 , 가장 많이 사용되는 방법이 HTTP 기반의 웹 서버를

사용하는 것이다 .

소켓과 관련된 처리는 HTTP 서버가 알아서 해주기 때문에

안드로이드 클라이언트 애플리케이션에 초점을 맞춘다 .

HTTP 는 상태를 유지하지 않는 프로토콜로서 사용자로

하여금 서버 쪽에 요청을 보내고 서버로부터 이에 대한 응답을

받을 수 있는 몇 가지 방법들을 제공한다 .

Unlocking Android

java.net.UrlConnection 을 보여주는 예제 (1/2)

13

public class SimpleGet extends Activity {. . .

public void onCreate(Bundle icicle) {. . .

this.getButton.setOnClickListener(new OnClickListener() {

public void onClick(View v) { getOutput.setText(""); String output = getHttpResponse(getInput.getText().toString()); // 화면에 출력하기 위해 if (output != null) { getOutput.setText(output); } } }); }; private String getHttpResponse(String location) { String result = null; URL url = null; Log.d(Constants.LOGTAG, " " + SimpleGet.CLASSTAG + " location = " + location); try { url = new URL(location); // 여러 가지 세부사항을 처리하는 URL 오브젝트 생성 Log.d(Constants.LOGTAG, " " + SimpleGet.CLASSTAG + " url = " + url); } catch (MalformedURLException e) { Log.e(Constants.LOGTAG, " " + SimpleGet.CLASSTAG + " " + e.getMessage()); }

getHttpResponse 메서드 호출

Unlocking Android

java.net.UrlConnection 을 보여주는 예제 (2/2)

14

if (url != null) { try { HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); BufferedReader in = new BufferedReader (new InputStreamReader(urlConn.getInputStream())); String inputLine; int lineCount = 0; // limit the lines for the example while ((lineCount < 10) && ((inputLine = in.readLine()) != null)) { lineCount++; Log.v(Constants.LOGTAG, " " + SimpleGet.CLASSTAG + " inputLine = " + inputLine); result += "\n" + inputLine; } in.close(); urlConn.disconnect(); // 수신 및 연결 종료 } catch (IOException e) { Log.e(Constants.LOGTAG, " " + SimpleGet.CLASSTAG + " " + e.getMessage()); } } else { Log.e(Constants.LOGTAG, " " + SimpleGet.CLASSTAG + " url NULL"); } return result; } }

HttpURLConnection 을 사용하여 서버에 연결 설정

출력을 위한 BufferedReader 생성

데이터 읽기

메서드를 사용하여 리턴 받은 문자열 뒤에 내용 추가

Unlocking Android

아파치 HttpClient API 사용 예제 (1/2)

15

public class ApacheHTTPSimple extends Activity { . . . private final Handler handler = new Handler() {

@Override public void handleMessage(final Message msg) { progressDialog.dismiss(); String bundleResult = msg.getData().getString("RESPONSE"); output.setText(bundleResult); } };

. . . private void performRequest() { final ResponseHandler<String> responseHandler = new ResponseHandler<String>() { public String handleResponse(HttpResponse response) { StatusLine status = response.getStatusLine(); Log.d(Constants.LOGTAG, " " + ApacheHTTPSimple.CLASSTAG + " statusCode - " + status.getStatusCode()); Log.d(Constants.LOGTAG, " " + ApacheHTTPSimple.CLASSTAG + " statusReasonPhrase - " + status.getReasonPhrase()); HttpEntity entity = response.getEntity(); String result = null; try { result = StringUtils.inputStreamToString(entity.getContent());

안드로이드에서는 HTTP 와 다중 스레드를 쉽게 사용할 수 있도록 해주는 java.net 클래스들을 더욱 잘 추상화 시킨 아파치 HttpClient 라이브러리 형태의 API 를 제공하고 있다 .

서로 다른 스레드에서 메시지를 주고받을 수 있는 헨들러 생성

핸들러를 사용하여 UI 업데이트

비동기 HTTP 사용을 위한 ResponseHandler 생성

handleResponse 콜백 구현

HTTP 응답 내용 받아오기

Unlocking Android

아파치 HttpClient API 사용 예제 (2/2)

16

Message message = handler.obtainMessage(); Bundle bundle = new Bundle(); bundle.putString("RESPONSE", result); message.setData(bundle); handler.sendMessage(message); } catch (IOException e) { Log.e(Constants.LOGTAG, " " + ApacheHTTPSimple.CLASSTAG, e); } return result; } }; this.progressDialog = ProgressDialog.show(this, "working . . .", "performing HTTP request"); new Thread() { // HTTP 호출을 위한 새로운 스레드 생성 @Override public void run() { try { DefaultHttpClient client = new DefaultHttpClient(); HttpGet httpMethod = new HttpGet(urlChooser.getSelectedItem().toString()); client.execute(httpMethod, responseHandler); } catch (ClientProtocolException e) { Log.e(Constants.LOGTAG, " " + ApacheHTTPSimple.CLASSTAG, e); } catch (IOException e) { Log.e(Constants.LOGTAG, " " + ApacheHTTPSimple.CLASSTAG, e); } } }.start(); } }

HttpGet 오브젝트 생성

HttpClient 를 사용하여 HTTP 실행

Unlocking Android

HC, PH, AH 의 관계 다이어그램

17

Non UI Thread – network request

Apache HttpClient

execute(method,

responseHandler)

Apache HttpClient

execute(method,

responseHandler)

Apache HttpClient

execute(method,

responseHandler)UI Thread – UI updates

HTTP request

HTTP response

HTTPserver

Unlocking Android

웹서비스

18

모호하게 사용되는 마케팅 용어 ? 명확한 표준 프로토콜 ?

기술 중립적인 네트워크 호스트들을 넘어 API 를 제공하는

수단 . 원격 메서드를 호출하거나 , 특정 플랫폼이나 벤더에

종속적이지 않고 독립적인 명력을 수행하여 원하는 결과를

얻게 하는 기술

POX : 기본적으로 HTTP 기반에서 XML 의 형태로 나타냄

REST : 리소스 개념을 사용하며 , HTTP 메서드와는 다르게 URL

형태로 접근하여 더 자세하게 데이터를 정의

SOAP : 가장 공식적인 방법으로 데이터 타입과 전송 메커니즘 및

보안에 대해 엄격한 규칙을 요구

Unlocking Android

POX – HTTP 와 XML 의 조합 (1/2)

19

public class DeliciousRecentPosts extends Activity { private static final String CLASSTAG = DeliciousRecentPosts.class.getSimpleName(); private static final String URL_GET_POSTS_RECENT = "https://api.del.icio.us/v1/posts/recent?";

. . . private final Handler handler = new Handler() { @Override public void handleMessage(final Message msg) { progressDialog.dismiss(); String bundleResult = msg.getData().getString("RESPONSE"); output.setText(parseXMLResult(bundleResult)); } }; @Override public void onCreate(final Bundle icicle) { super.onCreate(icicle); this.setContentView(R.layout.delicious_posts);

. . . this.button.setOnClickListener(new OnClickListener() { public void onClick(final View v) { output.setText(""); performRequest(user.getText().toString(), pass.getText().toString()); } }); };

del.icio.us URLPOX 서비스 사용은 URL 지정부터

시작핸들러를 사용하여 UI 업데이트

ID 와 패스워드로 로컬 performRequest를 호출하고 HttpClient 실행

사용자 ID 와 비밀번호를 가지고 HTTPS를 사용하는 사이트에 접속하여 최근 포스트 내용 혹은 북마크 목록을 읽어오는 예제

Unlocking Android

POX – HTTP 와 XML 의 조합 (2/2)

20

private void performRequest(final String user, final String pass) { this.progressDialog = ProgressDialog.show(this, "working . . .", "performing HTTP post to del.icio.us"); final ResponseHandler<String> responseHandler = HTTPRequestHelper.getResponseHandlerInstance(this.handler); new Thread() { public void run() { HTTPRequestHelper helper = new HTTPRequestHelper(responseHandler); helper.performPost(DeliciousRecentPosts.URL_GET_POSTS_RECENT, user, pass, null, null); } }.start(); } private String parseXMLResult(String xmlString) { StringBuilder result = new StringBuilder(); try { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); DeliciousHandler handler = new DeliciousHandler(); xr.setContentHandler(handler); xr.parse(new InputSource(new StringReader(xmlString))); List<DeliciousPost> posts = handler.getPosts(); for (DeliciousPost p : posts) { result.append("\n" + p.getHref()); } } catch (Exception e) { Log.e(Constants.LOGTAG, " " + DeliciousRecentPosts.CLASSTAG + " ERROR - " + e); } return result.toString(); } }

HTTP 를 위한 helper 사용

XML 을 사용 가능한 형태로 바꾸기 위해서 parseXMLResult 메서드 사용

Unlocking Android

REST

21

특정 리소스를 URI 형태로 만들고 서로 다른 액션을

수행하기 위해 다른 프로토콜 메서드를 사용한다 .

HTTP 에서 여러 가지 다른 작업을 수행하기 위해

POST(create, update, delete), GET(read),

PUT(create, replace), DELETE(delete) 등의 다양한

메소드를 활용하고 있다 .실제로 진정한 REST 구현은 많이 볼 수 없고 , REST

스타일의 API 를 더 많이 사용한다 .

Unlocking Android

SOAP

22

XML 스키마를 통해 트랜잭션 , 보안 , 암호 , 메시지

오케스트레이션과 메시지 구성법 , 그리고 WS- 표준과

관련된 모든 것들을 지원하고 있다 .

일반적으로 플랫폼에 상관없이 스마트폰과 같은 임베디드

기기처럼 소규모 시스템에는 권장되지 않는다 .

SOAP 를 사용하는 웹 서비스 시 모바일 기기에는 문제가 될

수 있는 현저한 오버헤드가 있으므로 REST 스타일 기반

아키텍쳐가 더 적합할 수 있다 .