I have two applications installed on the same device and they trying to connect to a multicast group the first application has a succeed connection the second one has error : listener failed with error Group entered state failed(POSIXErrorCode(rawValue: 48): Address already in use) I thought that allowLocalEndpointReuse allows several clients to connect to the same port
but it doesn't work.
let port = NWEndpoint.Port(portUdp) ?? NWEndpoint.Port(5353)
let host = NWEndpoint.Host(urlUdp)
guard let multicast = try? NWMulticastGroup(for:
[ .hostPort(host: host, port: port) ])
else {
stateMultiCast = "Error with url and port"
return
}
let parameters = NWParameters.udp
parameters.allowLocalEndpointReuse = true
parameters.allowLocalEndpointReuse
let group = NWConnectionGroup(with: multicast, using: parameters)
group.setReceiveHandler(maximumMessageSize: 16384, rejectOversizedMessages: true)
{ (message, content, isComplete) in
....
}
group.stateUpdateHandler = { (newState) in
print("Group entered state \(String(describing: newState))")
}
group.start(queue: .main)
How can i use the same port for several application so this application can receive all the same message sent by udp server ?
Thank you for your help
I found a solution different of multicast group that apple recommand :
func setupMulticastSocket(urlUdp : String, portUdp : String) -> Int32 {
let multicastAddress = urlUdp
let multicastPort: UInt16 = UInt16(portUdp) ?? 0
// Create a UDP socket
let socketFileDescriptor = socket(AF_INET, SOCK_DGRAM, 0)
guard socketFileDescriptor != -1 else {
print("Failed to create socket")
exit(1)
}
// Enable multicast loopback
var loop: UInt32 = 1
guard setsockopt(socketFileDescriptor, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, socklen_t(MemoryLayout<UInt32>.size)) != -1 else {
print("Failed to enable multicast loopback")
exit(1)
}
var reuseFlag: Int32 = 1
let reuseOption = withUnsafePointer(to: &reuseFlag) { ptr in
return UnsafeRawPointer(ptr).assumingMemoryBound(to: Int32.self)
}
if setsockopt(socketFileDescriptor, SOL_SOCKET, SO_REUSEPORT, reuseOption, socklen_t(MemoryLayout<Int32>.size)) == -1 {
print("Error setting SO_REUSEPORT: \(String(describing: strerror(errno)))")
return -1
}
if setsockopt(socketFileDescriptor, SOL_SOCKET, SO_REUSEADDR, reuseOption, socklen_t(MemoryLayout<Int32>.size)) == -1 {
print("Error setting SO_REUSEADDR: \(String(describing: strerror(errno)))")
return -1
}
// Bind the socket to a specific address and port
var socketAddress = sockaddr_in()
socketAddress.sin_len = __uint8_t(MemoryLayout<sockaddr_in>.size)
socketAddress.sin_family = sa_family_t(AF_INET)
socketAddress.sin_port = multicastPort.bigEndian
socketAddress.sin_addr.s_addr = CFSwapInt32HostToBig(INADDR_ANY)
withUnsafePointer(to: &socketAddress) { pointer in
let bindResult = pointer.withMemoryRebound(to: sockaddr.self, capacity: 1) { addrPointer in
bind(socketFileDescriptor, addrPointer, socklen_t(MemoryLayout<sockaddr_in>.size))
}
guard bindResult != -1 else {
print("Failed to bind socket")
exit(1)
}
}
// Join the multicast group
var multicastRequest = ip_mreq()
multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastAddress)
multicastRequest.imr_interface.s_addr = CFSwapInt32HostToBig(INADDR_ANY)
guard setsockopt(socketFileDescriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicastRequest, socklen_t(MemoryLayout<ip_mreq>.size)) != -1 else {
print("Failed to join multicast group")
exit(1)
}
return socketFileDescriptor
}
I call the function like that :
let socketFD = setupMulticastSocket(urlUdp: urlUdp, portUdp: portUdp)
if socketFD != -1 {
print("Multicast socket set up successfully.")
} else {
print("Failed to set up multicast socket.")
}
let bufferSize = 1024
var buffer = [UInt8](repeating: 0, count: bufferSize)
// Reading message received
while true {
let bytesRead = recv(socketFD, &buffer, buffer.count, 0)
if bytesRead > 0 {
let messageData = Data(bytes: buffer, count: bytesRead)
let hexString = messageData.reduce("") { $0 + String(format: "%02x", $1) }
let decodedData = Data(hexString: hexString)!
if let decodedData = Data(hexString: hexString){
newDataRsaReceived(decodedData ?? Data())
}
}
}
With this solution multiple client (application) can connect to the same port