我目前正在开发一个关于 iPhone 和 OBDKey 通过 wifi 进行通信的 iPhone 应用程序。到目前为止,一切都很好。我设法使用 CFStream 建立 TCP/IP 通信。我现在的问题:当我向 OBDKey 发送一些消息时,响应是完全相同的消息。
我认为错误代码位于应用程序的流方法中。但我无法弄清楚。
我希望你能给我一些建议。
这是代码:
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
NSInputStream *inputStream;
NSOutputStream *outputStream;
@implementation Communicator
@synthesize textField; //Gegenstück zu @property im .h File
@synthesize textView; //Gegenstück zu @property im .h File
- (IBAction)connectPressed:(id)sender {
host = @"192.168.0.74";
port = 23;
//Ausgabe
[self debugPrint:[NSString stringWithFormat:@"Setting up connection to %@ : %i", host, port]];
//Stream wird erzeugt mit Host, Port, Read & Write stream
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)(host), port, &readStream, &writeStream);
//Überprüfung ob Write Stream funktioniert
if (!CFWriteStreamOpen(writeStream)) {
[self debugPrint:[NSString stringWithFormat:@"Error, writeStream not open"]];
return;
}
//Methode open wird geöffnet
[self open];
[self debugPrint:[NSString stringWithFormat:@"Status of outputStream: %i", [outputStream streamStatus]]];
return;
}
//Hier werden sowohl der Output(Write)- als auch der Input(Read)-Stream geöffnet.
- (void)open {
[self debugPrint:[NSString stringWithFormat:@"Opening streams..."]];
//Da Automatic Reference Counting betrieben wird, muss eine __bridge Notation gesetzt werden um
//das Objekt hin und her verwenden zu können.
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
//RunLoop wird verwendet um input und output Objekte zu managen (Reihenfolgen usw.)
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
//Überprüfung ob beide Streams geöffnet wurden
if (!inputStream && !outputStream)
{
[self debugPrint:[NSString stringWithFormat:@"Error. Could not open streams!"]];
return;
}
//[self debugPrint:[NSString stringWithFormat:@"Streams are open"]];
}
//Disconnect Button wird gedrückt - Hierbei werden alle input und output streams geschlossen
//und RunLoops geschlossen
- (IBAction)disconnectPressed:(id)sender {
[inputStream close];
[outputStream close];
[inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream setDelegate:nil];
[outputStream setDelegate:nil];
inputStream = nil;
outputStream = nil;
[self debugPrint:[NSString stringWithFormat:@"Session closed!"]];
}
//Methode welche den eingegeben Text vom TextField in das TextView schreibt
- (IBAction)sendPressed:(id)sender {
//Hier wird überprüft ob eine Eingabe im textField erfolgt ist (ob Zeichen eingegeben wurden)
if ([[textField text] length] > 0) {
NSString *textFieldString = [textField text];
[self writeOut:(NSString *)textFieldString];
[self.textField endEditing:YES];
}
}
- (IBAction)clearViewPressed:(id)sender {
textView.text = nil;
}
//Methode in der Text formatiert im textView angezeigt werden kann
- (void)debugPrint:(NSString *)text {
textView.text = [textView.text stringByAppendingFormat: @"\n%@", text];
}
//Methode die Zuständig ist zum Stream handling
//NSStreamEventNone = 0
//NSStreamEventOpenCompleted = 1
//NSStreamHasBytesAvailable = 2
//NSStreamHasSpaceAvailable = 4
//NSStreamEventErrorOccurred = 8
//NSStreamEventEndEncountered = 16
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event {
if (stream.streamStatus == 2){
[self debugPrint:[NSString stringWithFormat:@"Stream opened"]];
}
switch (event) {
case NSStreamEventHasSpaceAvailable: {
if (stream == outputStream){
[self debugPrint:[NSString stringWithFormat:@"Ouput stream is ready!"]];
}
break;
}
case NSStreamEventHasBytesAvailable: {
if (stream == inputStream) {
[self debugPrint:[NSString stringWithFormat:@"Input stream is ready!"]];
uint8_t buf[1024];
unsigned int len = 0; //len wird nie negativ sein => unsigned
len = [inputStream read:buf maxLength:1024];
if (len > 0) {
NSMutableData* data=[[NSMutableData alloc] initWithLength:0];
//data wird mit Daten aus dem Buffer buf gefüttert (maximale Länge len)
[data appendBytes: (const void *)buf length:len];
//Erlaubt die Konvertierung eines Datenstrings in einen Characterstring
NSString *raw_data = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
//sends raw_data to readIn method
[self readIn:raw_data];
}
}
break;
}
default: {
[self debugPrint:[NSString stringWithFormat:@"Stream is sending an Event: %u", event]];
break;
}
}
}
- (void)readIn:(NSString *)s {
[self debugPrint:[NSString stringWithFormat:@"Reading:"]];
[self debugPrint:[NSString stringWithFormat:@"%@",s]];
}
- (void)writeOut:(NSString *)string {
uint8_t *buf = (uint8_t *)[string UTF8String];
[outputStream write:buf maxLength:strlen((char *)buf)];
[self debugPrint:[NSString stringWithFormat:@"%s\r\n",buf]];
//[self debugPrint:[NSString stringWithFormat:@"Sent:"]];
//[self debugPrint:[NSString stringWithFormat:@"%@\r\n",string]];
}
@end
先感谢您!!!
编辑 1:我已经在我的 Mac 上使用 Telnet (127.0.0.1:23) 的终端应用程序尝试了我的代码。发送和接收都完美无缺。但是来自 OBKey 的响应与我发送的请求相同。
编辑 2:我想通了:我必须发送初始化握手命令才能开始实际通信(ATZ、ATSP0 和 ATL1)。我已经在应用程序连接过程中调用的单独方法中完成了此操作。
问候,qoob