Search code examples
javaswiftsocketsinputstreamoutputstream

Send message through Socket Outputstream from Swift Client to Java Server


As the title says, I'm having some problems connecting my Swift Client to a Java Server by using only native libraries.

Right now I have a Java(client) to Java(server) connection, which works flawlessly, and a Swift(client) to Java(server) connection. My Swift client does connect to the Java server (it shows on the console), but the readFully of my server hangs - the only thing I see is the enormous message length on the console and that's pretty much it.

Swift Code (send):

func send(message: String) {
  let data = "msg:\(message)".data(using: .utf8)!

    data.withUnsafeBytes {
    guard let pointer = $0.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
      print("Error joining chat")
      return
    }
    out!.write(pointer, maxLength: data.count)
  }
}

Java Server (read):

int lenght = in.readInt();
System.out.println("Message: " + lenght);
if(length>0){
 byte[] message = new byte[length];
 in.readFully(message), 0, message.length); //This is where the problem is
}

So, basically the Java server hangs on the readFully method. Any ideas why that is? Whether I send a simple String or a Byte array, it always hangs, and for some reason the length is extremely big. Can someone help me understand what I'm doing wrong because I've around this for days and still didn't understand it (still pretty new to Swift).

Thank you very much!


Solution

  • In your Java code, you expect the first 4 bytes to be the length of the message, but in the Swift code, you didn't send the length of the message first. You sent the message itself directly. So now the Java code is left confused as to why the message is shorter than it expected, and waiting for more data to read.

    You can try sending the number of bytes in data first:

    let byteCountAsByteArray = withUnsafeBytes(of: Int32(data.count).bigEndian, Array.init)
    out!.write(byteCountAsByteArray, maxLength: 4)
    out!.write(pointer, maxLength: data.count)
    

    I suspect that you are using a DataInputStream in your Java code, hence .bigEndian. But if you are reading this in a little endian way, use .littleEndian instead.