samedi 9 mai 2015

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. App just worked fine in the iPhone application, but not getting stream in the mac application.

My Python Server Code

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

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

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

Aucun commentaire:

Enregistrer un commentaire