Reputation: 374
Context
outputStream.write(data)
) and wait for a response struct from mac app in input stream.Problem
fetchUser
request (after receiving response for loginUser
), mac app receives the request and writes the response without write
failing (-1)
but I am not receiving the response in iOS app. (Although I received the response for previous loginUser
request)Mac App code
let service: NetService = NetService(domain: "local.", type: "_my-app._tcp.", name: "test", port: 0)
service.delegate = self
service.publish(options: .listenForConnections)
//Writes response to connected output stream
func send(response: HalloResponse) {
do {
let data = try encoder.encode(response)
print("HalloServer: Response: \(String(describing: String(data: data, encoding: .utf8)))")
if serviceDelegate.dataStream?.outputSteam.write(data: data) == -1 {
print("HalloServer: send(response: HalloResponse) Write failied")
}
} catch {
print("HalloServer: Exception in send(request: Request)")
}
}
//NetServiceDelegate
func netService(_ sender: NetService, didAcceptConnectionWith inputStream: InputStream, outputStream: OutputStream) {
print("NetServiceDelegate: service - \(sender.name) inputStream - \(inputStream) outputStream \(outputStream)")
self.inputStream = inputStream
self.outputSteam = outputSteam
self.inputStream.delegate = self
self.outputSteam.delegate = self
self.inputStream.schedule(in: .main, forMode: .default)
self.inputStream.schedule(in: .main, forMode: .default)
self.inputStream.open()
self.inputStream.open()
}
// StreamDelegate
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
print("StreamDelegate: handle eventCode: \(eventCode.rawValue)")
if inputStream == aStream {
switch eventCode {
case .hasBytesAvailable:
var data = Data()
guard inputStream.read(data: &data) > 0 else { return }
print("HalloDataStream: Recieved data - \(String(describing: String(data: data, encoding: .utf8)))")
let decoder = JSONDecoder()
if let request = try? decoder.decode(Request.self, from: data) {
delegate?.didReceive(request: request)
}
if let response = try? decoder.decode(HalloResponse.self, from: data) {
delegate?.didReceive(response: response)
}
default: break
}
}
}
iOS App code
serviceBrowser.searchForServices(ofType: "_my-app._tcp.", inDomain: "local.")
func connect(with service: NetService, completion: @escaping DeviceConnectionCompletion) {
deviceCompletion = completion
let config = URLSessionConfiguration.default
config.requestCachePolicy = .reloadIgnoringLocalCacheData
let session = URLSession(configuration: config, delegate: self, delegateQueue: .main)
streamTask = session.streamTask(with: service)
streamTask?.resume()
streamTask?.captureStreams()
}
func send(request: Request) {
do {
let data = try encoder.encode(request)
print("HalloClient: Request: \(String(describing: String(data: data, encoding: .utf8)))")
if dataStream?.outputSteam.write(data: data) == -1 {
print("HalloClient: send(request: Request) Write failied")
}
} catch {
print("HalloClient: Exception in send(request: Request)")
}
}
// URLSessionStreamDelegate
func urlSession(
_ session: URLSession,
streamTask: URLSessionStreamTask,
didBecome inputStream: InputStream,
outputStream: OutputStream
) {
print("didBecomeInputStream:(NSInputStream *)inputStream outputStream: OutputStream")
deviceCompletion?(true)
self.inputStream = inputStream
self.outputSteam = outputSteam
self.inputStream.delegate = self
self.outputSteam.delegate = self
self.inputStream.schedule(in: .main, forMode: .default)
self.inputStream.schedule(in: .main, forMode: .default)
self.inputStream.open()
self.inputStream.open()
}
// StreamDelegate
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
// code exactly same as mac app delegate
}
Extensions on IO stream
extension InputStream {
private var maxLength: Int { return 4096 }
func read(data: inout Data) -> Int {
var totalReadCount: Int = 0
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: maxLength)
while hasBytesAvailable {
let numberOfBytesRead = read(buffer, maxLength: maxLength)
if numberOfBytesRead < 0, let error = streamError {
print("Read Error: \(error)")
break
}
data.append(buffer, count: numberOfBytesRead)
totalReadCount += numberOfBytesRead
}
return totalReadCount
}
}
extension OutputStream {
@discardableResult
func write(data: Data) -> Int {
if streamStatus != .open {
open()
}
let count = data.count
let result = data.withUnsafeBytes {
write($0.bindMemory(to: UInt8.self).baseAddress!, maxLength: count)
}
close()
return result
}
}
Would be really helpful if somebody can review my code and help me figure out the issue. I have a feeling that the issue is with stream open() and close(), Initially, nothing was working but adding open and close functions during write helped. Maybe I need a better way to fix this problem. PS: I had the same problem with CocoaAsyncSocket and I am not looking to use it or any other third party solution.
Upvotes: 1
Views: 720