简体   繁体   English

Mac Chat App,未获取NSInputStream和NSOutputStream

[英]Mac Chat App, Not getting NSInputStream & NSOutputStream

I am working with a chat application with a simple python localhost server, using NSStream to send and recieve data via network socket connection. 我正在使用带有简单python localhost服务器的聊天应用程序,使用NSStream通过网络套接字连接发送和接收数据。 App just worked fine in the iPhone application, but not getting stream in the mac application. App在iPhone应用程序中只能正常运行,但在Mac应用程序中却无法正常播放。

My Python Server Code 我的Python服务器代码

from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor

class MacChat(Protocol):
  def connectionMade(self):
    print "a client connected"
    self.factory.clients.append(self)
    print "clients are ", self.factory.clients
  def connectionLost(self, reason):
    self.factory.clients.remove(self)
  def dataReceived(self, data):
    a = data.split(':')
    print a
    if len(a) > 1:
        command = a[0]
        content = a[1]

        msg = ""
        if command == "iam":
            self.name = content
            msg = self.name + " has joined"

        elif command == "msg":
            msg = self.name + ": " + content
            print msg

        for c in self.factory.clients:
            c.message(msg)
  def message(self, message):
    self.transport.write(message + '\n')

factory = Factory()
factory.clients = []
factory.protocol = MacChat
reactor.listenTCP(80, factory)
print "Mac Chat server started"
reactor.run()

Mac 苹果电脑

ChatViewController.h ChatViewController.h

#import <Cocoa/Cocoa.h>
@interface ChatViewController : NSViewController
@property (strong,nonatomic) NSString *userName;
@end

ChatViewController.m ChatViewController.m

#import "ChatViewController.h"


@interface ChatViewController ()<NSTableViewDataSource,NSTableViewDelegate,NSStreamDelegate>
{
  NSInputStream *inputStream;
  NSOutputStream *outputStream;
  NSMutableArray * messages;
}
@property (weak) IBOutlet NSButton *btnSend;
@property (weak) IBOutlet NSTextField *txtMessage;
@property (weak) IBOutlet NSTableView *tableview;
@end

@implementation ChatViewController

- (void)viewDidLoad {
  [super viewDidLoad];

// Do view setup here.
}
-(void)setUserName:(NSString *)userName
{
  [self initNetworkCommunication];
  NSString *response  = [NSString stringWithFormat:@"iam:%@",userName];
  NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
  [outputStream write:[data bytes] maxLength:[data length]];
  messages = [[NSMutableArray alloc] init];
}

- (void)initNetworkCommunication {
  CFReadStreamRef readStream;
  CFWriteStreamRef writeStream;
  CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"localhost", 80, &readStream, &writeStream);
  inputStream = (__bridge_transfer NSInputStream *)readStream;
  outputStream = (__bridge NSOutputStream *)writeStream;
  inputStream.delegate=self;
  outputStream.delegate=self;
  [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  [inputStream open];
  [outputStream open];
}
- (IBAction)btnAtnSend:(id)sender {
  NSString *response  = [NSString stringWithFormat:@"msg:%@",   self.txtMessage.stringValue];
  NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
  [outputStream write:[data bytes] maxLength:[data length]];
  self.txtMessage.stringValue = @"";
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

// Get a new ViewCell
  NSTableCellView *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];

// Since this is a single-column table view, this would not be necessary.
// But it's a good practice to do it in order by remember it when a table is multicolumn.
  if( [tableColumn.identifier isEqualToString:@"cell"] )
  {
    NSString *s = (NSString *) [messages objectAtIndex:row];
    cellView.textField.stringValue = s;
  }
  return cellView;
}


- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
  return [messages count];
}
-(CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
  return 30;
}
#pragma mark NSStream Delegate

-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
  switch (eventCode) {

    case NSStreamEventOpenCompleted:
        NSLog(@"Stream opened");
        break;

    case NSStreamEventHasBytesAvailable:
        if (aStream == inputStream) {

            uint8_t buffer[1024];
            int len;

            while ([inputStream hasBytesAvailable]) {
                len = (int)[inputStream read:buffer maxLength:sizeof(buffer)];
                if (len > 0) {

                    NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];

                    if (nil != output) {
                        NSLog(@"server said: %@", output);
                        [self messageReceived:output];

                    }
                }
            }
        }
        break;

    case NSStreamEventErrorOccurred:
        NSLog(@"Can not connect to the host!");
        break;

    case NSStreamEventEndEncountered:
    {
        [aStream close];
        [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }
        break;

    default:
        NSLog(@"Unknown event");
  }
}
- (void) messageReceived:(NSString *)message {
  [messages addObject:message];
  [self.tableview reloadData];
  [self.tableview scrollRowToVisible:messages.count-1];
}
@end

OK. 好。 Looks like this is based on the example from raywenderlich.com . 看起来这是基于raywenderlich.com的示例。

The example is flawed, as mentioned by "glyph" in the comments section: 如注释部分中的“字形”所述,该示例有缺陷:

This tutorial makes some incorrect assumptions about how data is delivered to an application from a network. 本教程对如何将数据从网络传递到应用程序做出了一些不正确的假设。

Read glyph's post before building on this code. 在构建此代码之前,请先阅读字形的文章。

For your particular problem, you've made a lot of changes to the original code. 对于您的特定问题,您已经对原始代码进行了很多更改。 At a glance, it's not clear to me that "setUserName" is ever even called. 乍一看,我还不清楚“ setUserName”是否曾被调用过。

Without that, nothing else will happen. 没有那,什么都不会发生。

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

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