일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 스칼라
- 이더리움
- 파이썬 강좌
- 주키퍼
- CORDA
- 안드로이드 웹뷰
- akka 강좌
- 하이퍼레저 패브릭
- 파이썬 동시성
- 하이브리드앱
- play 강좌
- Play2 로 웹 개발
- 그라파나
- 파이썬
- 스위프트
- Actor
- play2 강좌
- Play2
- 파이썬 머신러닝
- hyperledger fabric
- 스칼라 동시성
- 파이썬 데이터분석
- 블록체인
- 엔터프라이즈 블록체인
- Hyperledger fabric gossip protocol
- Adapter 패턴
- Golang
- 스칼라 강좌
- Akka
- 플레이프레임워크
- Today
- Total
HAMA 블로그
[Swift 3 ] 가장 쉬운 소켓 (TCP) 통신 방법을 찾고 계신가요? 본문
[Swift 3 ] 가장 쉬운 소켓 (TCP) 통신 방법을 찾고 계신가요?
[하마] 이승현 (wowlsh93@gmail.com) 2016. 11. 24. 12:59iOS 앱개발과 스위프트라는 언어를 처음 시작하면서 소켓 통신 관련해서 좀 애를 먹고있다. 기능은 인증/푸쉬/전광판/사용히스토리/지도/음성인식/설정 정도인 prototype 앱을 2주안에 개발해야하는 촉박한 일정 탓에 약간 멘붕상태에서 봉주르,코코아,파운데이션,Object-C, Swift 2.0 / 3.0 , NSStream, 게임키트 같이 처음 시작하는 사람이 보기에 너무 많은 정보 속에 과연 어떻게 하면 쉽고 빠르게 개발을 할 수 있을까 하며 이것저것 뒤적뒤적 거렸는데 먼저 NSStream 을 이용해 봤다. 이게 가장 적합해 보였고 대략 코딩은 이러하다. (참고로 가장 쉬운 방법은 글 중간에 있으니..인내를)
let addr = "192.168.1.45"
let port = 22090
var inp : InputStream?
var out : OutputStream?
Stream.getStreamsToHost(withName: addr, port: port, inputStream: &inp, outputStream: &out)
let inputstream = inp!
let outputstream = out!
inputstream.open()
outputstream.open()
outputstream.write(query,maxLength:query.characters.count)
let buffersize = 1024
var buffer = [UInt8](repeating :0, count : buffersize)
let bytesRead = inputstream.read(&buffer, maxLength: buffersize)
var getString : NSString?
if(bytesRead>0){
getString = NSString(bytes: buffer, length: bytesRead, encoding: String.Encoding.utf8.rawValue)
return getString as! String
}else{
return PKConst.connection_fail
}
inputstream.close()
outputstream.close()
이렇게 자바IO 스타일로 코딩을 했는데 뭐 주고 받는것은 문제가 없으나 문서를 다시 읽어 본 결과 Streme 은 ( 참고로 swift 3.0 에서는 NS 같은 쓸데없는 prefix 가 빠졌다. 속이 다 시원하다.) 아래처럼 RunLoop 등 비동기식으로 써야 맞는거다.
inputstream.delegate = self
outputstream.delegate = self
inputstream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
outputstream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
NSStreamEventOpenCompleted
NSStreamEventHasSpaceAvailable
NSStreamEventHasBytesAvailable
NSStreamEventEndEncountered
NSStreamEventErrorOccurred
이런게 있는거 봐선 느낌상 Reactor 패턴식 (멀티플렉싱) 으로 통신하는게 정석인듯 싶은데 점점 골치 아파 오기 시작한다. Object-C 는 완전한 예제들이 있는듯한데 개인적으로 Object-C 를 굉장히 싫어하며 , 이 와중에 공부해서 포팅하고 싶지도 않다.
참고로 swift 3.0 으로 구현된 Stream 예제는 대략 다음과 같으나 확실치 않고 추천하고 싶지 않다.
(동기적,비동기적 각각 완전한 예제를 발견하지 못했다. 좋은 예제를 가지고 계신분은 홍익인간의 정신으로 공유좀 ㅜㅜ )
import Foundation
class Connection: NSObject, StreamDelegate {
var host:String?
var port:Int?
var inputStream: InputStream?
var outputStream: OutputStream?
var sneds = Queue<String>()
func connect(host: String, port: Int) {
self.host = host
self.port = port
Stream.getStreamsToHost(withName:host, port: port, inputStream: &inputStream, outputStream: &outputStream)
if inputStream != nil && outputStream != nil {
// Set delegate
inputStream!.delegate = self
outputStream!.delegate = self
// Schedule
inputStream!.schedule(in: .main, forMode: RunLoopMode.defaultRunLoopMode)
outputStream!.schedule(in: .main, forMode: RunLoopMode.defaultRunLoopMode)
print("Start open()")
// Open!
inputStream!.open()
outputStream!.open()
}
}
func stream(aStream: Stream, handleEvent eventCode: Stream.Event) {
if aStream === inputStream {
switch eventCode {
case Stream.Event.errorOccurred:
print("input: ErrorOccurred: ")
case Stream.Event.openCompleted:
print("input: OpenCompleted")
case Stream.Event.hasBytesAvailable:
print("input: HasBytesAvailable")
// Here you can `read()` from `inputStream`
default:
break
}
}
else if aStream === outputStream {
switch eventCode {
case Stream.Event.errorOccurred:
print("output: ErrorOccurred: ")
case Stream.Event.openCompleted:
print("output: OpenCompleted")
case Stream.Event.hasSpaceAvailable:
print("output: HasSpaceAvailable")
// Here you can write() to `outputStream`
default:
break
}
}
}
}
class SimpleSocketUtil {
static func checkID ( id : String) -> Bool {
let conn = Connection()
conn.connect(host: "192.168.1.45", port: 22090)
return true
}
}
여튼 이러한 와중에 나를 구원해 준것이 있었으니 SwiftSocket!! 아래를 참고하시라.
SwiftSocket
https://github.com/swiftsocket/SwiftSocket
무지무지 하기 쉽다.
1. 디펜던시 추가
ytcpsocket.c / ytcpsocket.swift / ysocket.swift 이 3개를 자신의 프로젝트에 추가시킨다.
2. Connection 예제
func connect(query : String){
let addr = "192.168.1.45"
let port = 22090
let client:TCPClient = TCPClient(addr: "192.168.1.45", port: 22090)
var (success,errmsg)=client.connect(timeout: 1)
if success{
var (success,errmsg)=client.send(str:"GET / HTTP/1.0\n\n" )
if success{
let data=client.read(1024*10)
if let d=data{
if let str=String(bytes: d, encoding: String.Encoding.utf8){
print(str)
}
}
}else{
print(errmsg)
}
}else{
print(errmsg)
}
}
API 예제들을 간단히 살펴보면 아래와 같다.
api usage
create client socket
//create a socket connect to www.apple.com and port at 80
var client:TCPClient = TCPClient(addr: "www.apple.com", port: 80)
connect with timeout
var (success, errmsg) = client.connect(timeout: 10)
send data
var (success, errmsg) = client.send(str:"GET / HTTP/1.0\n\n")
//or you can send binnary data
//socket.send(data:[Int8])
read data
var data = client.read(1024*10) //return optional [Int8]
close socket
var (success, errormsg) = client.close()
create servert socket
var server:TCPServer = TCPServer(addr: "127.0.0.1", port: 8080)
listen
var (success, msg) = server.listen()
accept
var client = server.accept() //now you can use client socket api to read and write
client socket example
//创建socket
var client:TCPClient = TCPClient(addr: "www.apple.com", port: 80)
//连接
var (success, errmsg) = client.connect(timeout: 1)
if success {
//发送数据
var (success, errmsg) = client.send(str:"GET / HTTP/1.0\n\n" )
if success {
//读取数据
var data = client.read(1024*10)
if let d = data {
if let str = String.stringWithBytes(d, length: d.count, encoding: NSUTF8StringEncoding){
println(str)
}
}
}else {
println(errmsg)
}
} else {
println(errmsg)
}
server socket example (echo server)
func echoService(client c:TCPClient) {
println("newclient from:\(c.addr)[\(c.port)]")
var d = c.read(1024*10)
c.send(data: d!)
c.close()
}
func testserver(){
var server:TCPServer = TCPServer(addr: "127.0.0.1", port: 8080)
var (success, msg) = server.listen()
if success {
while true {
if var client = server.accept() {
echoService(client: client)
} else {
println("accept error")
}
}
} else {
println(msg)
}
}
'아이폰 (IOS) ' 카테고리의 다른 글
[Swift 3.0] Queue (0) | 2016.11.24 |
---|---|
[Swift 3.0] LinkedList (0) | 2016.11.24 |
iOS 개발에서 스토리보드 란 무엇인가? (0) | 2016.11.22 |
iOS 와 안드로이드에서의 병렬 쓰레드 개발 (AsyncTask 와 GCD) (0) | 2016.11.21 |
스위프트로 TCP 소켓을 다루어보자 [번역] (0) | 2016.11.17 |