맥이나 iOS에서 소켓 프로그래밍을 구현하기 위해 직접 BSDSocket 혹은 CFSocket을 사용해서 만드는 방법이 있습니다. 그러나 저처럼 처음부터 쌓기 싫어하는 사람을 위해서 잘 포장된 라이브러리가 있는데 그것이 바로 CocoaAsyncSocket입니다.
https://github.com/robbiehanson/CocoaAsyncSocket
예전에는 구글 코드에 있었는데 현재는 github에서 진행되고 있습니다. 오픈소스이고, 간혹 버그가 생기는 경우도 있습니다만 (직접 경험) 개발자에게 알려주니 며칠 뒤에 고쳐져 있더군요.
이 라이브러리의 사용법은 생각외로 간단합니다.
다운 받는 방법
다른 프로그램을 사용할 필요 없이 해당 버튼만 누르면 zip 형태로 받을 수 있습니다.
압축을 풀면 폴더와 파일이 나옵니다. 다른 폴더는 신경쓰지 않고, 소켓 라이브러리만 본다면 두 폴더로 나눌 수 있습니다
RunLoop : AsyncSocket(.h/.m) AsyncUdpSocket(.h/.m)
GCD : GCDAsyncSocket(.h/.m) GCDAsyncUdpSocket(.h/.m)
tcp와 udp는 보면 구별가실테고, GCD는 모르겠으면 검색해 봅시다.
런루프 폴더의 라이브러리는 업데이트가 중단된지 꽤 되었습니다. 안정성도 보장할 수 없습니다. 코드를 보고 어떤 구조인지 파악하기에는 문제 없을지도 모르나, 실 사용에서는 권장하지 않습니다.
GCD 폴더에는 GCD를 사용해 thread-safe하게 설계되었습니다. 실제 사용할 목적이라면 이 쪽을 사용하도록 합시다.
기본적인 사용 방법은 아주 간단합니다. 그냥 프로젝트에 해당 파일을 넣으면 됩니다. 가령 UDP 소켓 통신을 원한다면 GCDAsyncUdoSocket라는 이름의 두 파일만 추가해서 사용하면 됩니다.
예제는 폴더 안에 들어있는 예제들을 참고하시면 됩니다.
라고 하고 끝나면 부실하니 간단하게 사용하는 설명을 해보죠. 저는 UDP를 구현한지라 UDP를 중심으로 설명하겠습니다. TCP와 큰 차이는 없을테니 다른 포함된 예제를 보시고 비교하면서 공부해보도록 합시다.
사용하기 전에 우선 헤더 파일에 해당되는 GCDAsyncUdpSocket.h를 해당 헤더 파일에 포함시킵니다.
그리고 소켓을 선언해 주셔야 되는데 대략 이런 방식으로 하시면 됩니다.
@interface UDPSocket : UIViewController {
long tag;
GCDAsyncUdpSocket *udpSocket;
}
long 타입은 특별한 경우가 아니면 하나로도 충분하고, 소켓의 경우에는 필요에 따라서 여러개를 사용할 수도 있습니다. 물론 여러개를 사용하려고 한다면 선언도 그에 맞춰서 해줘야겠죠.
소스 코드에서의 처리는 다음과 같습니다.
- (void) viewDidLoad()
{
//.......
udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
if (![udpSocket bindToPort:0 error:&error]) {
NSLog(@"Error binding: %@", error);
return;
}
if (![udpSocket beginReceiving:&error]
{
NSLog(@"Error receiving: %@", error);
return;
}
}
viewDidLoad에서 구현하는 이유는 미리 선언을 해주어 이후에 사용하기 편하게 하기 위해서입니다.
딱히 따로 설명할 것은 없고, 코드를 보면 무슨 기능을 하는지 대충 감이 오리라 생각됩니다.
위 작업을 행한 다음에 실제로 데이터를 주고 받을때는 이렇게 합니다.
[udpSocket sendData:data toHost:host port:port withTimeout:0.5 tag:tag];
data는 NSData형식입니다. 다른 데이터 전송 방식이 있는지는 잘 모르겠네요.
host는 보낼 대상의 ip, port는 포트 번호입니다.
withTimeout은 타임아웃 시간 설정입니다. 0일때는 타임아웃을 하지 않고, 이외의 양수의 경우에는 해당 시간(초)만큼 기다려도 응답이 오지 않으면 그만두는거죠.
보내는 것은 위와 같이 하고, 받는 것은 아래와 같이 합니다.
TCP와 UCP가 다른 것은 이 부분입니다만, 약간의 함수명 차이만 있고 사용법은 비슷합니다.
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag
{
}
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error
{
}
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address withFilterContext:(id)filterContext
{
}
UDP에서는 위의 3가지를 포함시켜야 합니다. 실제 구현내용이 없어도 되니 꼭 넣어주도록 합시다.
UDP의 특성상 보냈는지 확인하는 2개의 함수는 별 내용이 없어도 되더군요. TCP라면 신경써서 체크해줘야겠지만 말입니다.
세번째가 데이터를 받았을 때 처리하는 함수입니다.
라이브러리가 쉬워서 별로 설명할건 없네요. 기본적인건 위 수준에서 원하는걸 조금 고치는 정도로도 충분합니다.
'iOS' 카테고리의 다른 글
iOS5 Customizing Navigation Bar (네비게이션바 커스터마이징) (0) | 2012.09.03 |
---|---|
Custom Tab Bars (0) | 2012.09.03 |
iOS5에서 NSJSONSerialization을 사용해서 JSON 다루기 예제 (0) | 2012.08.28 |
GCD와 Block을 이용해서 비동기 방식으로 URL 이미지 로드하기 (0) | 2012.08.27 |
UIActivityIndicator – whilst loading map pins in background thread. (0) | 2012.08.27 |