http://www.elabs.se/blog/66-using-websockets-in-native-ios-and-android-apps
이 샘플은 WebSocket으로 실시간으로 browser, iOS, android 클라이언트와 통신하는 방법에 대한 것이다.
서버는 웹소켓서버를 운영하고 여러가지 플랫폼과 통신을 수행이 가능해진다. 전체 소스는 https://github.com/elabs/mobile-websocket-example 을 참고하라.
서버
아주 간단한 웹소켓서버의 예는 아래와 같다.EM-WebSocket gem을 사용하고 Ruby로 구현되었다.
equire "em-websocket"
EventMachine.run do
@channel = EM::Channel.new
EventMachine::WebSocket.start(host: "0.0.0.0", port: 8080, debug: true) do |ws|
ws.onopen do
sid = @channel.subscribe { |msg| ws.send(msg) }
@channel.push("#{sid} connected")
ws.onmessage { |msg| @channel.push("<#{sid}> #{msg}") }
ws.onclose { @channel.unsubscribe(sid) }
end
end end |
웹소켓연결을 8080포트에서 수락한고 새로운 클라이언트가 연결되면 내부 채널을 구독한다. 클라이언트가 데이터를 이 채널에 전송하여 채널에 데이터가 유효해질때마다 모든 클라이언트에 데이터를 전송한다. 클라이언트는 구독ID를 통해 구별이 가능하다. 클라이언트가 연결이 끊어지면 채널의 구독을 중단한다.
위코드를 실행하려면 bundle install , ruby server.rb을 순서대로 실행한다.
Browser client
$(document).ready(function() {
ws = new WebSocket("ws://" + location.hostname + ":8080/");
ws.onmessage = function(event) {
$("#messages").append("<p>" + event.data + "</p>");
};
ws.onclose = function() {
console.log("Socket closed");
};
ws.onopen = function() {
console.log("Connected");
ws.send("Hello from " + navigator.userAgent);
};
$("#new-message").bind("submit", function(event) {
event.preventDefault();
ws.send($("#message-text").val());
$("#message-text").val("");
}); }); |
서버에 8080포트로 연결을 하고 연결이 되었을 때, 메세지가 도달하였을 때, 그리고 연결이 닫혔을떄의 콜백을 구현하였다.
새로운 메세지를 작성하고 메세지를 전송하기 위한 submit form도 작성하였다.
이 코드는 모던브라우져만 지원한다. 오래된 브라우져에서는 Flash로 가능하다.
iOS client
SocketRocket이라는 라이브러리로 웹소켓을 사용할 수 있다. 이것은 Cocoapods로 설치가 가능하다. 먼저 Cocoapods를 설치해야 한다.
Podfile을 아래와 같이 iOS프로젝트가 있는 폴더에서 만든다.
platform :ios, "7.0" pos "SocketRocket" |
Cocoapods가 설치되어 잇지 않다면 gem install cocoapods 을 실행하고 pod setup을 실행 이어서 pod install을 Podfile이 들어 있는 iOS프로젝트 폴더에서 실행한다.
관련 코드는 ViewController.m에 웹소켓서버에 연결하는 코드를 작성한다.
-(void) connectWebSocket { webSocket.delegate = nil; webSocket = nil; NSString *urlString = @"ws://localhost:8080"; SRWebSocket *newWebSocket = [[SRWebSocket alloc] initWithURL initWithURL:[NSURL URLWithString:urlString]]; newWebSocket.delegate = self; [newWebSocket open]; } |
localhost부분을 서버주소로 바꾸면 된다.
다음은 SRWebSocketDelegete protocol의 구현이다.
- (void)webSocketDidOpen:(SRWebSocket *)newWebSocket { webSocket = newWebSocket; [webSocket send:[NSString stringWithFormat:@"Hello from %@", [UIDevice currentDevice].name]]; } - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error { [self connectWebSocket]; } - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean { [self connectWebSocket]; } - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message { self.messagesTextView.text = [NSString stringWithFormat:@"%@\n%@", self.messagesTextView.text, message]; } |
브라우져에서 사용하는 자바스크립트 API와 완전 비슷하다.
메세지를 보낼때는 다음과 같이
-(IBAction)sendMessage:(id)sender { [webSocket send:self.messageTextField.text]; self.messageTextField.text =nil; } |
Android client
Android Studio를 사용한다면 Java WebSockets라이브러리를 gradle로 설치한다
dependencies { compile "org.java-websocket:Java-WebSocket:1.3.0" } |
ADT를 사용한다면 maven으로 java WebSocket을 설치하던가 아니면 별도로 배포되는 jar을 받아서 사용하던가 하면 된다
private void connectWebSocket() { URI uri; try { uri = new URI("ws://websockethost:8080"); } catch (URISyntaxException e) { e.printStackTrace(); return; } mWebSocketClient = new WebSocketClient(uri) { @Override public void onOpen(ServerHandshake serverHandshake) { Log.i("Websocket", "Opened"); mWebSocketClient.send("Hello from " + Build.MANUFACTURER + " " + Build.MODEL); } @Override public void onMessage(String s) { final String message = s; runOnUiThread(new Runnable() { @Override public void run() { TextView textView = (TextView)findViewById(R.id.messages); textView.setText(textView.getText() + "\n" + message); } }); } @Override public void onClose(int i, String s, boolean b) { Log.i("Websocket", "Closed " + s); } @Override public void onError(Exception e) { Log.i("Websocket", "Error " + e.getMessage()); } }; mWebSocketClient.connect(); } |
websockethost는 수정하라.
메세지 보 낼때는 이렇게
public void sendMessage(View view) { EditText editText = (EditText)findViewById(R.id.message); mWebSocketClient.send(editText.getText().toString()); editText.setText(""); } |
android.permission.INTERNET권한이 있어야 하고 앱타겟을 Android 4.0+이다.