TCP(Transmission Control Protocol) 통신은 데이터 전송을 위한 프로토콜 중 하나로, 신뢰성 있는 연결형 통신을 제공한다.
TCP 통신은 Swift에서는 Network 프레임워크, SwiftSocket, StarScream 라이브러리 등을 사용할 수 있다. Objective-C에서는 NSStream 클래스, CocoaAsyncSocket, GCDAsyncSocket, SocketRocket, CFNetwork 라이브러리 등을 사용해서 처리할 수 있다.
아래 예제는 Swift와 Network 프레임워크를 사용해서 구현했다!
import Network
class TCPServer {
let listener: NWListener
let queue = DispatchQueue(label: "TCPServerQueue")
init(port: UInt16) throws {
let parameters = NWParameters.tcp
listener = try NWListener(using: parameters, on: NWEndpoint.Port(rawValue: port)!)
}
func start() {
print("서버 시작")
listener.newConnectionHandler = { newConnection in
print("새로운 클라이언트 연결 감지")
self.handleConnection(connection: newConnection)
}
listener.start(queue: queue)
}
private func handleConnection(connection: NWConnection) {
connection.start(queue: queue)
receive(on: connection)
}
}
class TCPClient {
let connection: NWConnection
let queue = DispatchQueue(label: "TCPClientQueue")
init(host: String, port: UInt16) {
let endpoint = NWEndpoint.Host(host)
let port = NWEndpoint.Port(rawValue: port)!
connection = NWConnection(host: endpoint, port: port, using: .tcp)
}
func start() {
connection.stateUpdateHandler = { state in
switch state {
case .ready:
print("서버 연결 완료")
self.receive()
case .failed(let error):
print("서버 연결 실패: \(error)")
default:
break
}
}
connection.start(queue: queue)
}
}
send
메소드를 사용하여 서버에 메시지를 전송한다. 이때 메시지는 UTF-8 인코딩으로 변환되어 전송된다.receive
메소드를 통해 클라이언트로부터 데이터를 수신해서 UTF-8로 디코딩하여 문자열로 변환되고, 이를 클라이언트에게 다시 전송한다.// 클라이언트
func send(message: String) {
let data = message.data(using: .utf8)
connection.send(content: data, completion: .contentProcessed { error in
if let error = error {
print("클라 전송 실패: \(error)")
} else {
print("클라 전송 성공: \(message)")
}
})
}
// 서버
private func receive(on connection: NWConnection) {
connection.receive(minimumIncompleteLength: 1, maximumLength: 1024) { [weak self] data, context, isComplete, error in
if let error = error {
print("서버측 받기 실패: \(error)")
connection.cancel()
return
}
if let data = data, let message = String(data: data, encoding: .utf8) {
print("서버측 받기 성공: \(message)")
// 응답 전송 (optional)
self?.send(message, on: connection)
}
if isComplete {
connection.cancel()
} else {
self?.receive(on: connection)
}
}
}
connection.cancel
메소드를 호출하여 연결을 종료한다.// 클라이언트
if isComplete {
self?.connection.cancel()
}
// 서버
if isComplete {
print("연결 종료")
connection.cancel()
}
해당 코드는 로컬호스트에서 통신하는 코드이다.
만약 다른 네트워크에 있는 호스트와 통신할 경우 서버는 공인 IP 주소를 사용해 외부 네트워크에서 접근할 수 있어야 한다.
클라이언트는 서버의 공인 IP주소와 포트번호로 연결을 시도하고, 서버는 클라이언트의 연결을 수락한다.
이 과정에서 클라이언트와 서버는 서로의 IP 주소와 포트 번호를 알고 있어야 하며, 이를 기반으로 통신을 진행한다.