我尝试编写Swift片段来向Telnet发送命令,但我需要先登录.
在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$
Run Code Online (Sandbox Code Playgroud)
在命令行中,Telnet要求我输入用户名和密码.之后我可以运行任何Linux命令.到现在为止还挺好.
我为Android编写了Telnet模块,因此OSX Telnet服务正常工作.这意味着我看到login:并password:输出所以我能够处理它.
现在我坚持使用iOS Swift,我用Google搜索并找到了非常好的解决方案,应该适用于我的情况:
所以我写了我的家庭作品:
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)")
}
}
Run Code Online (Sandbox Code Playgroud)
流回调覆盖方法来自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
}
}
Run Code Online (Sandbox Code Playgroud)
首先,当我试着打电话时没有任何反应initNetworkCommunication().我希望打电话func stream 或我错了?.它应该是NSStreamEvent.HasBytesAvailable国家还是我错了?
当我打电话sendMessage("snags"),我得到的回应中stream落在上case NSStreamEvent.HasSpaceAvailable.这是什么意思?
我的预期结果:在连接上我应该得到login:输出但什么也得不到.
Sat*_*ito -1
您几乎已经完成了 NSStreamDelegate 的工作,但您需要了解“rfc 854 telnet 协议规范”。
之前的通信需要主机和您的代码之间进行 telnet 协商。
在回调的“NSStreamEvent.HasBytesAvailable”情况下,转储缓冲区,转换为 NSData,例如
NSLog( "%@", NSData(bytes: buffer, length: len) )
Run Code Online (Sandbox Code Playgroud)
你会得到
<fffd18ff fd20fffd 23fffd27 fffd24>
Run Code Online (Sandbox Code Playgroud)
这是telnet协商,必须按照规范进行响应。
第二个问题。
NSStreamEvent.HasSpaceAvailable 表示“一个布尔值,指示接收器是否可以写入。”
在通过 NSOutputStream 发送消息之前,您必须在“sendMessage”方法中检查 NSOutputStream 的 hasSpaceAvailable 属性。
或者使用队列来发送数据并在 NSStreamEvent.HasBytesAvailable 上发送它,这是我的建议。
看这个答案。 如何使用 NSInputStream 和 NSOutputStream
| 归档时间: |
|
| 查看次数: |
475 次 |
| 最近记录: |