왕논의 연구실

[iOS] MQTT를 이용한 채팅서비스 만들기 - 구현 본문

iOS/iOS

[iOS] MQTT를 이용한 채팅서비스 만들기 - 구현

ywangnon 2020. 4. 23. 22:48

화면은

  • 연결됐는지 보여주는 뷰
  • 채팅창으로 쓸 테이블뷰
  • host 주소를 입력할 뷰(귀찮아서 그냥 넣고 싶기도 한데, 개인 host주소를 입력하기 꺼려져서 입력으로 바꿈)
  • 채팅창
  • 연결 버튼
  • 해제 버튼

만들때는 별거 없는거 같은데 일일이 나열하니 많은거 같다. 그래서 topic도 입력할 수 있게 할까 했다가 화면에 텍스트뷰 많아지는게 보기 짜증날꺼 같아서 고정시켰다.

 

브로커 생성과 브로커 연결(Connect)

import MQTTClient

private var transport = MQTTCFSocketTransport()
private var session = MQTTSession()
    
self.transport.host = host
self.transport.port = 1883
        
self.session?.transport = transport

// 연결
self.session?.connect(connectHandler: { (error) in
	if error != nil {
		// 오류 처리
	} else {
		// 연결 성공
	}
})

 

연결 해제(Disconnect)

self.session?.close(disconnectHandler: { (error) in
	if error != nil {
		// 오류 처리
	} else {
		// 해제 처리
	}
})

 

토픽에 구독(Subcribe)

self.session?.delegate = self
// 구독
self.session?.subscribe(toTopic: self.topic, 
			at: .exactlyOnce, 
			subscribeHandler: { (error, gQoss) in
	if error != nil {
		// 오류 처리
	} else {
		print("Subcription Successfull! Granted Qos: ", gQoss)
	}
})

at에는 QoS 레벨을 넣는다.

MQTT는 3단계의 QoS(Quality of service)를 제공한다.

  • 0 : 메시지는 한번만 전달하며, 전달여부를 확인하지 않는다. Fire and Forget 타입이다. (atMostOnce)
  • 1 : 메시지는 반드시 한번 이상 전달된다. 하지만 메시지의 핸드셰이킹 과정을 엄밀하게 추적하지 않기 때문에, 중복전송될 수도 있다.(atLeastOnce)
  • 2 : 메시지는 한번만 전달된다. 메시지의 핸드셰이킹 과정을 추적한다. 높은 품질을 보장하지만 성능의 희생이 따른다.(exactlyOnce)

토픽에 게시(Publish)

session?.publishData("\(message)@\(id)" .data(using: .utf8, allowLossyConversion: false), 
			onTopic: self.topic, 
                    retain: false, 
                    qos: .exactlyOnce, 
                    publishHandler: { (error) in
	if error != nil {
		// 에러 처리
	} else {
		// 성공 처리
	}
})
  • 데이터는 입력한 텍스트와 id를 합쳐서 데이터타입으로 변환했다. 이유는...

새 메세지

func newMessage(_ session: MQTTSession!, 
		data: Data!, 
                onTopic topic: String!, 
                qos: MQTTQosLevel, 
                retained: Bool, 
                mid: UInt32) {
	print("New Message ID::: ", mid)
        
	if let newMessage = String(bytes: data, encoding: .utf8) {
		if let messageBody = newMessage.components(separatedBy: "@").first,
			let userID = newMessage.components(separatedBy: "@").last {
			// 메세지 처리
		}
	}
}

새 메세지를 받는 받아서 처리하는데 ID와 메세지를 구분해서 얻기 위함이다.

@를 이용해서 구분하여 ID와 메세지를 얻는다.

id는 전체 코드를 보면 알겠지만 그냥 기기 uuid로 했다. 간단한 구현이므로 기기 uuid랑 같으면 내 메세지, 다르면 다른 사람 메세지 물론 아이디가 표현되는건 아니므로 누가 말했는지는 모른다. 나중에 고도화 하던지 해보자!!

 

전체 코드: https://github.com/ywangnon/MQTT_Chatting