Получение ответа от TCP-сервера на клиенте Swift
Я пытаюсь написать клиент сокета TCP в swift, используя GCDAsyncSocket, но у меня есть одна проблема. В моем коде у меня есть NSTextField (называется box) и вот мой код:
import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate
{
@IBOutlet weak var window: NSWindow!
@IBOutlet weak var box: NSTextField!
var bsocket: GCDAsyncSocket!
func applicationDidFinishLaunching(aNotification: NSNotification?)
{
bsocket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
var port:UInt16 = 8090
if (!bsocket.connectToHost("localhost", onPort: port, error: nil))
{
println("Error")
}
else
{
println("Connecting...")
}
var request:String = "Arn.Preg:3302:"
var data:NSData = request.dataUsingEncoding(NSUTF8StringEncoding)!
bsocket.writeData(data, withTimeout: -1.0, tag: 0)
bsocket.readDataWithTimeout(-1.0, tag: 0)
}
func applicationWillTerminate(aNotification: NSNotification?)
{
// Insert code here to tear down your application
}
func socket(socket : GCDAsyncSocket, didReadData data:NSData, withTag tag:UInt16)
{
var response = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Received Response")
box.stringValue = box.stringValue + "\n" + response
}
func socket(socket : GCDAsyncSocket, didConnectToHost host:String, port p:UInt16)
{
println("Connected to \(host) on port \(p).")
box.stringValue = box.stringValue + "\n" + "Connected to \(host) on port \(p)."
}
}
func socket(socket : GCDAsyncSocket, didReadData data:NSData, withTag tag:UInt16)
Когда я использую команду telnet в терминале, чтобы попытаться получить доступ к моему TCP-серверу, это результат.
Marzuk:~ marzukrashid$ telnet localhost 8090
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Arn.TipoSer:XPL0:
Затем, когда я набираю "Arn.Preg:3302:", сервер возвращает это:
Marzuk:~ marzukrashid$ telnet localhost 8090
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Arn.TipoSer:XPL0:
Arn.Preg:3302:
Arn.Resp:3302=329351:
Когда я набираю "Arn.Preg: 3302:" сервер возвращает "Arn.Resp:3302=329351:", это результат, которого я пытаюсь достичь, я хочу, чтобы NSTextField в моем приложении отображал "Arn.Resp:3302=329351:". Прямо сейчас, когда я запускаю свой код, программа регистрирует "Соединение...", "Подключено к 127.0.0.1 через порт 8090" и "Полученный ответ", как это должно быть, и в NSTextField в самом приложении, на нем отображается "Подключено к 127.0.0.1 через порт 8090". и "Arn.TipoSer:XPl0:", как и должно быть, но он не отображает "Arn.Resp:3302=329351:", как я хочу это тоже.
Мой вопрос: почему мой код этого не делает, и как я могу исправить свой код в этом.
Благодарю.
2 ответа
Я узнал, что функция didReadData запускается только при запуске функции readDataWithTimeout, поэтому я добавил функцию readDataWithTimeout в didConnectToHost, didReadData и applicationDidFinishLaunching. Я узнал, что "\n" требуется в конце запроса, чтобы дать нажатие клавиши возврата, используемой в терминале, поэтому я добавил "\n" к "Arn.Preg:3302:", чтобы сделать это "Arn.Preg:3302:\ п". Окончательный код выглядел так:
import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
@IBOutlet weak var box: NSTextField!
//let bsocket = GCDAsyncSocket(delegate: AppDelegate.self, delegateQueue: dispatch_get_main_queue())
var bsocket: GCDAsyncSocket!
func applicationDidFinishLaunching(aNotification: NSNotification?)
{
bsocket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
var port:UInt16 = 8090
if (!bsocket.connectToHost("localhost", onPort: port, error: nil))
{
println("Error.")
}
else
{
println("Connecting...")
}
bsocket.readDataWithTimeout(-1.0, tag: 0)
}
func applicationWillTerminate(aNotification: NSNotification?) {
// Insert code here to tear down your application
}
func socket(socket : GCDAsyncSocket, didReadData data:NSData, withTag tag:UInt16)
{
var response = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Received Response")
box.stringValue = box.stringValue + "\n" + response
bsocket.readDataWithTimeout(-1.0, tag: 0)
}
func socket(socket : GCDAsyncSocket, didConnectToHost host:String, port p:UInt16)
{
println("Connected to \(host) on port \(p).")
box.stringValue = box.stringValue + "\n" + "Connected to \(host) on port \(p)."
bsocket.readDataWithTimeout(-1.0, tag: 0)
sendRequest()
}
func sendRequest()
{
var request:String = "Arn.Preg:3302:\n"
var data:NSData = request.dataUsingEncoding(NSUTF8StringEncoding)!
bsocket.writeData(data, withTimeout: -1.0, tag: 0)
}
}
Мне кажется, вы пытаетесь отправить Arn.Preg:3302:
сообщение и получить ответ, прежде чем вы на самом деле подключился. В вашем applicationDidFinishLaunching
Вы инициируете асинхронное соединение, а затем немедленно вызываете writeData
а также readData
- вам, вероятно, нужно сделать что-то вроде:
class AppDelegate: NSObject, NSApplicationDelegate
{
@IBOutlet weak var window: NSWindow!
@IBOutlet weak var box: NSTextField!
var bsocket: GCDAsyncSocket!
func applicationDidFinishLaunching(aNotification: NSNotification?)
{
bsocket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
var port:UInt16 = 8090
if (!bsocket.connectToHost("localhost", onPort: port, error: nil))
{
println("Error")
}
else
{
println("Connecting...")
}
}
func socket(socket : GCDAsyncSocket, didReadData data:NSData, withTag tag:UInt16)
{
var response = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Received Response")
box.stringValue = box.stringValue + "\n" + response
}
func socket(socket : GCDAsyncSocket, didConnectToHost host:String, port p:UInt16)
{
println("Connected to \(host) on port \(p).")
box.stringValue = box.stringValue + "\n" + "Connected to \(host) on port \(p)."
var request:String = "Arn.Preg:3302:"
var data:NSData = request.dataUsingEncoding(NSUTF8StringEncoding)!
bsocket.writeData(data, withTimeout: -1.0, tag: 0)
bsocket.readDataWithTimeout(-1.0, tag: 0)
}
}