在OSX上我生成了一个Telnet服务:launchctl load -F /System/Library/LaunchDaemons/telnet.plist.之后我能够从其他计算机连接到IP:XXX.XXX.X.XXX端口23.
例如,从Windows 7:
telnet XXX.XXX.X.XXX 23 ..... Darwin/BSD (fess.local) (ttys009) login: snaggs Password:xxxxxx snaggs:~ lur$
在命令行中,Telnet要求我输入用户名和密码.之后我可以运行任何Linux命令.到现在为止还挺好.
我为Android编写了Telnet模块,因此OSX Telnet服务正常运行.这意味着我看到登录:和密码:输出,所以我能够处理它.
现在我坚持使用iOS Swift,我用Googled找到了非常好的解决方案,应该适用于我的情况:
> receiving-data-from-nsinputstream-in-swift
> using-sockets-in-swift-like-in-java
所以我写了我的家庭作品:
class TelnetClient : NSObject,NSStreamDelegate{ private var inputStream: NSInputStream! private var outputStream: NSOutputStream! func initNetworkCommunication(){ let host : CFString = "XXX.XXX.X.XXX" let port : UInt32 = 23 var readstream : Unmanaged<CFReadStream>? var writestream : Unmanaged<CFWriteStream>? CFStreamCreatePairWithSocketToHost(kcfAllocatorDefault,host,port,&readstream,&writestream) // var _inputStream: NSInputStream? // var _outputStream: NSOutputStream? // NSStream.getStreamsToHostWithName("XXX.XXX.X.XXX",port: 23,inputStream: &_inputStream,outputStream: &_outputStream) // self.inputStream = _inputStream! // self.outputStream = _outputStream! 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() } func sendMessage(message:String){ let data: NSData = message.dataUsingEncoding(NSASCIIStringEncoding,allowLossyConversion: true)! //NSUTF8StringEncoding let stream: NSInputStream = NSInputStream(data: data) var buffer = [UInt8](count: 8,repeatedValue: 0) stream.open() if stream.hasBytesAvailable { let result :Int = stream.read(&buffer,maxLength: buffer.count) } self.outputStream.write(&buffer,maxLength: buffer.count) println("wrote to Server: \(message)") } }
来自NSStreamDelegate的流回调覆盖方法:
func stream(aStream: NSStream,handleEvent eventCode: NSStreamEvent) { switch (eventCode){ case NSStreamEvent.ErrorOccurred: NSLog("ErrorOccurred") break case NSStreamEvent.EndEncountered: NSLog("EndEncountered") break case NSStreamEvent.None: NSLog("None") break case NSStreamEvent.HasBytesAvailable: NSLog("HasBytesAvaible") // ... NEVER ENTERS HERE var buffer = [UInt8](count: 4096,repeatedValue: 0) if ( aStream == self.inputStream){ while (self.inputStream.hasBytesAvailable){ var len = self.inputStream.read(&buffer,maxLength: buffer.count) if(len > 0){ var output = NSString(bytes: &buffer,length: buffer.count,encoding: NSUTF8StringEncoding) if (output != ""){ NSLog("server said: %@",output!) } } } } break //case NSStreamEvent.allZeros: // NSLog("allZeros") // break case NSStreamEvent.OpenCompleted: NSLog("OpenCompleted") // <-- called on initialisation break case NSStreamEvent.HasSpaceAvailable: NSLog("HasSpaceAvailable") break default: NSLog("default") break } }
首先,当我尝试调用initNetworkCommunication()时没有任何反应.我希望调用func流或者我错了?它应该是NSStreamEvent.HasBytesAvailable状态还是我错了?
当我调用sendMessage(“snags”)时,我得到流中的响应,该响应属于NSStreamEvent.HasSpaceAvailable案例.这是什么意思?
解决方法
在通信之前,需要在主机和代码之间进行telnet协商.
在你的回调’NSStreamEvent.HasBytesAvailable’的情况下,转储你的缓冲区,转换为NSData,就像
NSLog( "%@",NSData(bytes: buffer,length: len) )
你会得到
<fffd18ff fd20fffd 23fffd27 fffd24>
这是telnet协商,你必须根据规范做出回应.
第二个问题.
NSStreamEvent.HasSpaceAvailable意味着’一个布尔值,指示是否可以写入接收器.’
在通过NSOutputStream发送消息之前,必须在“sendMessage”方法中检查NSOutputStream的hasSpaceAvailable属性.
或者使用队列来发送数据并在NSStreamEvent.HasBytesAvailable上发送它,这是我的建议.