简体   繁体   English

Swift iOS和Java套接字之间的TCP通信

[英]TCP communication between Swift iOS and Java Sockets

I'm trying to establish a communication between my Java application and the relative (work in progress) iOS application. 我正在尝试在我的Java应用程序和相对(正在进行中的)iOS应用程序之间建立通信。 After sockets are opened, the iOS application (client) write an "handshake" string into stream and then it wait on read stream (I think). 打开套接字后,iOS应用程序(客户端)将“握手”字符串写入流,然后等待读取流(我认为)。 Contemporary the Java application (server, started before the iOS application) open with success the socket and wait on BufferedReader for read the "handshake" and at this point both applications are blocked. 当代Java应用程序(服务器,在iOS应用程序之前启动)成功打开套接字并等待BufferedReader读取“握手”,此时两个应用程序都被阻止。 I don't understand how it is possible? 我不明白它是怎么可能的?

Follow the part of iOS code: 按照iOS代码的一部分:

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 part of Java code (it work perfectly between other computers using the same Java application): 遵循Java代码的一部分(它在使用相同Java应用程序的其他计算机之间完美地工作):

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 unlock from the read, print correctly the received handshake and then continue his job. 当我关闭iOS应用程序时,Java应用程序从读取中解锁,正确打印收到的握手,然后继续他的工作。 Someone can help me please? 有人可以帮帮我吗?

I think your problem is that you never end the line in Swift program. 我认为你的问题是你永远不会在Swift程序中结束这一行。

What readLine does according to BufferReader's documentation: readLine根据BufferReader的文档做了什么:

"Reads a line of text. A line is considered to be terminated by any one of a line feed ('\\n'), a carriage return ('\\r'), or a carriage return followed immediately by a linefeed." “读取一行文字。一行被认为是由换行符('\\ n'),回车符('\\ r')或回车符后面的任何一行终止。”

This means that it expects either a newline character, or the end of the communication. 这意味着它需要换行符或通信结束。 Since your Swift application doesn't send any newline char and doesn't close the stream, the client just waits. 由于您的Swift应用程序不发送任何换行符并且不关闭流,因此客户端只是等待。

Try to put a line feed ('\\n') or a carriage return ('\\r') and see how it goes. 尝试添加换行符('\\ n')或回车符('\\ r'),看看它是怎么回事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM