220 likes | 515 Views
6. 네트워크와 서비스. 네트워크 (1/4). 사용자는 API 들과 네트워크 프로토콜들을 사용함으로써 하위 계층에서 데이터를 전달하는 방법 , 데이터의 신뢰성 등에 대한 걱정 없이 하위 레벨인 애플리케이션 쪽에만 집중할 수 있음. 노드 (Node) : 네트워크란 특정 주소를 가진 기기들이 서로 연결되어 데이터 송수신이 가능한 것을 말함 . 특정 주소를 가진 기기들을 ‘ 노드 ’ 라 함. 네트워크 (2/4). 레이어와 프로토콜 - 프로토콜 : 통신을 위한 규약 및 방법들을 사전에 정의한 것
E N D
네트워크 (1/4) 사용자는 API들과 네트워크 프로토콜들을 사용함으로써 하위 계층에서 데이터를 전달하는 방법, 데이터의 신뢰성 등에 대한 걱정 없이 하위 레벨인 애플리케이션 쪽에만 집중할 수 있음 노드(Node) : 네트워크란 특정 주소를 가진 기기들이 서로 연결되어 데이터 송수신이 가능한 것을 말함. 특정 주소를 가진 기기들을 ‘노드’라 함 Unlocking Android
네트워크 (2/4) 레이어와 프로토콜 - 프로토콜 : 통신을 위한 규약 및 방법들을 사전에 정의한 것 - 레이어: 네트워크 프로토콜 스택의 각 부분을 추상화한 것 - Link Layer : 물리적인 장치와 주소를 묶어주는 역할 ARP/RARP 등과 같은 물리 주소 변환 프로토콜들을 포함 - Internet Layer : 주소변환과데이터 구성을 담당 IP의 여러 버전과 ping 프로토콜, ICMP 등이 있음 - Transport Layer : 실제 데이터 전송. HTTP, FTP, SMTP, IMAP, POP, DNS, SSH,SOAP 등의 등용 레벨 프로토콜들을 포함 Unlocking Android
네트워크 (3/4) IP 레이어: IP주소를 할당하고 데이터를 전송 단위인 패킷(Packet)으로 나누어전송하는 일을 담당하는데 패킷을데이터그램(Datagram)으로 표현. 헤더정보 등을 포함하여 한 번에 보낼 수 있는 데이터의 크기(MTU) 등을 정의 - IP주소 : 각 패킷의 발신지와 송신지를 알려줌 - 32bit IP주소는 IPv4로써 네 개의 섹션으로 나누어 10진수로 표현 - ‘127‘로시작 : 항상 사용하는 시스템의 루프백/로컬주소 나타냄 - ‘10/192’: 라우팅이 불가능한 주소. 같은 로컬 네트워크 세그먼트 안에 있는 기기들끼리는 통신할 수 있지만 외부 네트워크에 존재하는 기가들과는 불가능 - IP네트워크에서의 패킷라우팅 작업은 라우터에 의해서 결정됨 Unlocking Android
네트워크 (4/4) TCP와 UDP - TCP : 여분의 데이터를 추가하여 패킷들의 순서를 처리하고 패킷이 정확히 도착했을 경우 ACK(acknowledgement)를 통해 정확하게 도착했는지 확인하므로 데이터 전송의 신뢰성을 기대할 수 있음. - UDP : 순서대로 데이터 패킷을 보내거나 ACK를 받는 부분이 없어 단순히 데이터 전송만 할 뿐 상대방에게 제대로 전달되었는지에 대해서는 책임지지 않음. 애플리케이션 레이어 프로토콜 : TCP/UDP를 사용하는 트랜스포트 레이어에서패킷이 전달되면 애플리케이션이 이 내용을 처리함. Unlocking Android
클라이언트와 서버 데이터는 하나의 통일된 형태로 중앙 서버에 저장되고, 클라이언트는 데이터를 검색하거나 데이터를 이용한 작업을 하기 위해 HTTP와 같은 프로토콜을 사용하여 서버에 접속함 다양한 목적으로 하나의 IP주소를 사용하는 서버에 동시에 접속하는 많은 클라이언트를 처리하기 위해 포트사용. - Well known Ports : 0 ~ 1023 - Registered Ports : 1024 ~ 49151 - Dynamic/Private Ports : 49152 ~ 65535 Unlocking Android
서버 소켓을 이용한 통신 서버 소켓: 특정 IP주소와 포트에 대해 데이터를 쓰거나 읽을 수 있는 스트림을 의미 소켓을 사용함으로써 데이터의 형태나 패킷 크기 등의 걱정없이 데이터를 전송할 수 있게 해주며 네트워크의 추상화를 통하여 프로그래머의 수고를 덜어줌 소켓을 사용한다는 것은 오늘날 시스템에서 사용하는 POSIX 표준을 따른다는 것을 의미하므로 소켓과 관련된 모든 작업을 파일 I/O 형태로 처리해야 함 Unlocking Android
소켓 사용 예제 (1/2) public final class EchoServer extends Thread { private static final int PORT = 8889; privateEchoServer() {} public static void main(String args[]) { EchoServerechoServer = 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) 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) /* 패키지 명 및 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) 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; }; } 입력을 위한 BufferedWriter설정 소켓에 내용 쓰기 출력을 위한 BufferedReader설정 Unlocking Android
HTTP 사용하기 데이터 전송이 가능한 서버 프로그램이 이미 존재하고 그것을 사용할 수 있다면, 가장 많이 사용되는 방법이 HTTP 기반의 웹 서버를 사용하는 것이다. 소켓과 관련된 처리는 HTTP 서버가 알아서 해주기 때문에 안드로이드 클라이언트 애플리케이션에 초점을 맞춘다. HTTP는 상태를 유지하지 않는 프로토콜로서 사용자로 하여금 서버 쪽에 요청을 보내고 서버로부터 이에 대한 응답을 받을 수 있는 몇 가지 방법들을 제공한다. Unlocking Android
java.net.UrlConnection을 보여주는 예제 (1/2) 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) if (url != null) { try { HttpURLConnectionurlConn = (HttpURLConnection) url.openConnection(); BufferedReader in = new BufferedReader (new InputStreamReader(urlConn.getInputStream())); String inputLine; intlineCount = 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) 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) 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(); HttpGethttpMethod = 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의 관계 다이어그램 Non UI Thread – network request Apache HttpClient execute(method,responseHandler) HTTP request HTTP server Apache HttpClient execute(method,responseHandler) HTTP response Apache HttpClient execute(method,responseHandler) UI Thread – UI updates Unlocking Android
웹서비스 모호하게 사용되는 마케팅 용어? 명확한 표준 프로토콜? 기술 중립적인 네트워크 호스트들을 넘어 API를 제공하는 수단. 원격 메서드를 호출하거나, 특정 플랫폼이나 벤더에 종속적이지 않고 독립적인 명력을 수행하여 원하는 결과를 얻게 하는 기술 POX : 기본적으로 HTTP 기반에서 XML의 형태로 나타냄 REST : 리소스 개념을 사용하며,HTTP 메서드와는 다르게 URL 형태로 접근하여 더 자세하게 데이터를 정의 SOAP : 가장 공식적인 방법으로 데이터 타입과 전송 메커니즘 및 보안에 대해 엄격한 규칙을 요구 Unlocking Android
POX – HTTP와 XML의 조합 (1/2) 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 URL POX 서비스 사용은 URL 지정부터 시작 핸들러를 사용하여 UI 업데이트 사용자 ID와 비밀번호를 가지고 HTTPS를 사용하는 사이트에 접속하여 최근 포스트 내용 혹은 북마크 목록을 읽어오는 예제 ID와 패스워드로 로컬 performRequest를 호출하고 HttpClient실행 Unlocking Android
POX – HTTP와 XML의 조합 (2/2) 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 { SAXParserFactoryspf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReaderxr = 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 특정 리소스를 URI 형태로 만들고 서로 다른 액션을 수행하기 위해 다른 프로토콜 메서드를 사용한다. HTTP에서 여러 가지 다른 작업을 수행하기 위해 POST(create, update, delete), GET(read), PUT(create, replace), DELETE(delete) 등의 다양한 메소드를 활용하고 있다. 실제로 진정한 REST 구현은 많이 볼 수 없고, REST 스타일의 API를 더 많이 사용한다. Unlocking Android
SOAP XML 스키마를 통해 트랜잭션, 보안, 암호, 메시지 오케스트레이션과 메시지 구성법, 그리고 WS- 표준과 관련된 모든 것들을 지원하고 있다. 일반적으로 플랫폼에 상관없이 스마트폰과 같은 임베디드 기기처럼 소규모 시스템에는 권장되지 않는다. SOAP를 사용하는 웹 서비스 시 모바일 기기에는 문제가 될 수 있는 현저한 오버헤드가 있으므로 REST 스타일 기반 아키텍쳐가 더 적합할 수 있다. Unlocking Android