TCP communication between Swift iOS and Java sockets

I am trying to establish a connection between my Java application and the corresponding (incomplete) IOS application. After the sockets are open, the iOS application (client) writes the โ€œhandshakeโ€ line to the stream and then waits for the read stream (I think). A modern Java application (a server running before an iOS application) successfully opens a socket and waits for a BufferedReader to read a "handshake", and at this point both applications are blocked. I do not understand how this is possible?

Follow the piece of iOS code:

public class Client: NSObject, NSStreamDelegate { var serverAddress: CFString let serverPort: UInt32 = 50000 private var inputStream: NSInputStream! private var outputStream: NSOutputStream! private var connecting:Bool init(ip:String) { serverAddress = ip connecting = false super.init() connect() } func connect() { connecting = true while connecting { print("connecting...") var readStream: Unmanaged<CFReadStream>? var writeStream: Unmanaged<CFWriteStream>? CFStreamCreatePairWithSocketToHost(nil, self.serverAddress, self.serverPort, &readStream, &writeStream) // Documentation suggests readStream and writeStream can be assumed to // be non-nil. If you believe otherwise, you can test if either is nil // and implement whatever error-handling you wish. self.inputStream = readStream!.takeRetainedValue() self.outputStream = writeStream!.takeRetainedValue() self.inputStream.delegate = self self.outputStream.delegate = self self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) self.inputStream.open() self.outputStream.open() // send handshake let handshake: NSData = "handshake".dataUsingEncoding(NSUTF8StringEncoding)! let returnVal = self.outputStream.write(UnsafePointer<UInt8>(handshake.bytes), maxLength: handshake.length) print("written: \(returnVal)") // wait to receive handshake let bufferSize = 1024 var buffer = Array<UInt8>(count: bufferSize, repeatedValue: 0) print("waintig for handshake...") let bytesRead = inputStream.read(&buffer, maxLength: bufferSize) if bytesRead >= 0 { var output = NSString(bytes: &buffer, length: bytesRead, encoding: NSUTF8StringEncoding) print("received from host \(serverAddress): \(output)") } else { // Handle error } connecting = false self.inputStream.close() self.outputStream.close() } } public func stream(stream: NSStream, handleEvent eventCode: NSStreamEvent) { print("stream event") if stream === inputStream { switch eventCode { case NSStreamEvent.ErrorOccurred: print("input: ErrorOccurred: \(stream.streamError?.description)") case NSStreamEvent.OpenCompleted: print("input: OpenCompleted") case NSStreamEvent.HasBytesAvailable: print("input: HasBytesAvailable") // Here you can `read()` from `inputStream` default: break } } else if stream === outputStream { switch eventCode { case NSStreamEvent.ErrorOccurred: print("output: ErrorOccurred: \(stream.streamError?.description)") case NSStreamEvent.OpenCompleted: print("output: OpenCompleted") case NSStreamEvent.HasSpaceAvailable: print("output: HasSpaceAvailable") // Here you can write() to `outputStream` break default: break } } } 

}

Follow the piece of Java code (it works great between other computers using the same Java application):

 public void run() { System.out.println("Server.java: waiting for connection"); //accept try { serverSocket = new ServerSocket(portNumber); clientSocket = serverSocket.accept(); reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())); System.out.println("Server.java: connected to " + clientSocket.getInetAddress()); // check for input request type String line = reader.readLine(); // <----BLOCKED HERE! if(line.equals("handshake")) { connected = true; // send acceptation System.out.println("Server.java: Sending handshake, waiting response"); writer.write("handshake"); writer.newLine(); writer.flush(); // .... and the rest of code... 

When I close the iOS application, the Java application unlocks from reading, correctly prints the received handshake, and then continues to work. Can anybody help me?

+5
source share
1 answer

I think your problem is that you never end a line in a Swift program.

What readLine does according to the BufferReader documentation:

"Reads a line of text. A line is considered to be completed by any of line ('\ n'), carriage return ('\ r') or carriage return, after which the line returns immediately."

This means that it expects either a newline or the end of the message. Since your Swift application does not send a new char line or close the stream, the client is just waiting.

Try putting a line feed ('\ n') or a carriage return ('\ r') and see how this happens.

+3
source

All Articles