728x90
반응형
SMALL
예제 코드
*설정 앱 -> Wi-Fi -> IP 주소에서 IP주소를 찾고 밑의 코드에 "기기의 IPAddress"부분을 수정해주세요.
import UIKit
class ViewController: UIViewController {
let ipAddress = "기기의 IPAddress" // 메시지를 전송할 IP 주소를 저장한다.
let port: UInt16 = 12345 // 메시지를 전송할 포트 번호를 저장한다.
let receivedMessageLabel = UILabel() //수신된 메시지를 출력할 UILabel 객체를 생성한다.
var count:Int = 0 // 수신된 메시지의 수를 저장할 변수를 선언한다.
//UDP 메시지를 전송하는 함수를 선언한다.
func sendUDPMessage(message: String, ipAddress: String, port: UInt16) {
// sockaddr_in 객체를 생성하고 서버의 IP 주소와 포트 번호를 설정한다.
var serverAddress = sockaddr_in( // sockaddr_in 구조체는 IPv4 주소를 나타내며, 이를 초기화하는 코드입니다.
sin_len: __uint8_t(MemoryLayout<sockaddr_in>.size), // sin_len은 구조체의 크기를 의미하며, MemoryLayout<sockaddr_in>.size로 해당 구조체의 크기를 지정합니다.
sin_family: sa_family_t(AF_INET), // sin_family는 주소 체계를 지정하는데, AF_INET으로 IPv4를 사용하겠다는 것을 나타냅니다.
sin_port: in_port_t(port).bigEndian, // sin_port는 포트 번호를 나타내며, in_port_t(port).bigEndian으로 입력받은 포트 번호를 빅 엔디안 형식으로 지정합니다.
sin_addr: in_addr(s_addr: inet_addr(ipAddress)), // sin_addr은 IP 주소를 나타내며, INADDR_ANY를 사용하여 모든 IP 주소에서 수신할 수 있도록 합니다.
sin_zero: (0, 0, 0, 0, 0, 0, 0, 0) // sin_zero는 구조체의 나머지 부분을 모두 0으로 초기화합니다.
)
// 클라이언트 소켓을 생성한다.
var clientSocket = socket(AF_INET, SOCK_DGRAM, 0)
// 메시지를 C 스타일 문자열로 변환하고, sendto() 함수로 UDP 메시지를 전송한다.
let sent = message.withCString {
sendto(
clientSocket,
$0,
Int(strlen($0)),
0,
sockaddr_cast(&serverAddress),
socklen_t(MemoryLayout<sockaddr_in>.size)
)
}
// 메시지 전송에 실패한 경우 에러 메시지를 출력한다.
if sent < 0 {
print("Error sending message: (sent)")
}
// 클라이언트 소켓을 닫는다.
close(clientSocket)
}
// sockaddr_cast 함수를 정의한다.
func sockaddr_cast(_ p: UnsafeMutableRawPointer) -> UnsafeMutablePointer<sockaddr> {
return p.assumingMemoryBound(to: sockaddr.self)
}
// UDP 메시지를 수신하는 함수를 정의한다.
func receiveUDPMessage(port: UInt16) {
// sockaddr_in 객체를 생성하고 수신할 포트 번호를 설정한다.
var serverAddress = sockaddr_in(
sin_len: __uint8_t(MemoryLayout<sockaddr_in>.size),
sin_family: sa_family_t(AF_INET),
sin_port: in_port_t(port).bigEndian,
sin_addr: in_addr(s_addr: INADDR_ANY),
sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)
)
// 서버 소켓을 생성한다.
var serverSocket = socket(AF_INET, SOCK_DGRAM, 0)
// bind() 함수를 호출하여 소켓을 주소와 연결한다.
var status = bind(
serverSocket,
sockaddr_cast(&serverAddress),
socklen_t(MemoryLayout<sockaddr_in>.size)
)
// 소켓 연결에 실패한 경우 에러 메시지를 출력한다.
if status != 0 {
print("Error binding socket")
return
}
// 클라이언트 주소 정보를 저장할 sockaddr_in 객체를 생성한다.
var clientAddress = sockaddr_in()
// 클라이언트 주소 정보의 길이를 저장한다.
var clientAddressLength = socklen_t(MemoryLayout<sockaddr_in>.size)
// 수신된 메시지를 저장할 버퍼를 생성한다.
var buffer = [CChar](repeating: 0, count: 1024)
// 무한 루프를 돌면서 메시지를 수신하고 출력한다.
while true {
// recvfrom() 함수를 호출하여 UDP 메시지를 수신한다.
let bytesRead = recvfrom(
serverSocket,
&buffer,
buffer.count,
0,
sockaddr_cast(&clientAddress),
&clientAddressLength
)
// 수신된 메시지를 String 객체로 변환한다.
let message = String(cString: buffer)
DispatchQueue.main.async { // UI 업데이트는 메인 스레드에서 실행되어야 함
self.count += 1
self.receivedMessageLabel.text = "Received message: \(message) \(self.count)"
}
}
}
// 버튼이 눌릴 때 호출되는 함수
@objc func buttonPressed(sender: UIButton) {
sendUDPMessage(message: "Hello, UDP!", ipAddress: ipAddress, port: port)
}
// 예제를 위한 메시지 전송
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type: .system)
button.setTitle("Send Message", for: .normal)
button.addTarget(self, action: #selector(buttonPressed(sender:)), for: .touchUpInside)
view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
receivedMessageLabel.text = "UDP?"
receivedMessageLabel.textColor = .red
// 라벨 설정
receivedMessageLabel.textAlignment = .center
receivedMessageLabel.font = UIFont.systemFont(ofSize: 20)
receivedMessageLabel.numberOfLines = 0
view.addSubview(receivedMessageLabel)
// 라벨 위치 설정
receivedMessageLabel.translatesAutoresizingMaskIntoConstraints = false
receivedMessageLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 50).isActive = true
receivedMessageLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
receivedMessageLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
// 비동기적으로 함수 실행
DispatchQueue.global(qos: .background).async {
self.receiveUDPMessage(port: self.port)
}
}
}
시뮬레이터에서 버튼 터치 시 아이폰에서 Received message: \(message) \(self.count) 메세지를 확인 가능합니다. :)
728x90
반응형
LIST
'iOS' 카테고리의 다른 글
객체지향의 역할, 책임 차이 쉬운 예 (0) | 2023.05.03 |
---|---|
솔리드(SOLID) 원칙 (0) | 2023.05.03 |
TCP, UDP (0) | 2023.04.29 |
강한순환참조 (0) | 2023.04.28 |
AppDelegate (0) | 2023.04.27 |