iOS - 从NSStream发出接收数据

时间:2014-08-05 16:52:00

标签: ios xcode stream nsstream

我正在制作一个感应iBeacons的应用程序。当你进入iBeacon的直接范围时,应用程序将信标的主要和次要编号发送到服务器,服务器发送回存储在MySQL数据库中的图像,根据主要和次要编号发送回不同的图像

应用程序通过NSStream将主要和次要编号发送到Python(扭曲套接字)脚本,该脚本使用这些编号从数据库中获取图像并将其发送回应用程序。

当我使用它从数据库中获取简单的文本消息时,这个设置很有用,但是当我尝试在应用程序内接收和显示图像时遇到了问题。

首先我将发布流的代码:handleEvent,它接收来自输入流的数据。

代码只是对本教程http://www.raywenderlich.com/3932/networking-tutorial-for-ios-how-to-create-a-socket-based-iphone-app-and-server

的略微修改
// input stream event that recieves the data from the server
//
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{

switch (eventCode)
{
    case NSStreamEventOpenCompleted:
        NSLog(@"stream opened");
        break;


    case NSStreamEventHasBytesAvailable: // event for recieving data

        NSLog(@"Recieved Data");

        if (aStream == _inputStream)
        {
            uint8_t buffer[500000];
            int len;

            // loop gets bytes from input stream
            //
            while ([_inputStream hasBytesAvailable])
            {
                len = [_inputStream read:buffer maxLength:sizeof(buffer)];

                if (len > 0)
                {

                    NSString *str = @"data:image/jpg;base64,";
                    NSString *img = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
                    str = [str stringByAppendingString:img];
                    NSData *ImgOut = [NSData dataWithContentsOfURL:[NSURL URLWithString:str]];


                    if (nil != ImgOut)
                    {

                        self.ImageView.image = [UIImage imageWithData:ImgOut];
                        NSLog(@"show image");

                    }
                }
            }

        }

        break;



    case NSStreamEventErrorOccurred:
        NSLog(@"can not connect to host");
        [self initNetworkComms];

        break;

    case NSStreamEventEndEncountered:
        NSLog(@"Connection Lost");

        [_outputStream close];
        [_inputStream close];
        [self initNetworkComms];

        break;

    default:
        NSLog(@"unkown event");

        break;
}
}

为了好的衡量标准,我将发布Python脚本的代码

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

import mysql.connector

db = mysql.connector.connect(user='NotImportant', password='WouldntYouLikeToKnow', host='localhost', database='retailbeacons')
cursor = db.cursor()

class MessageServer(Protocol):
    def connectionMade(self):

        self.factory.clients.append(self)
        print "clients are ", self.factory.clients



    def connectionLost(self, reason):

        self.factory.clients.remove(self)
        print "client has disconnected"



    def dataReceived(self, data):

        a = data.split(':')

        if len(a) > 1:
            Major = a[0]
            Minor = a[1]

            msg = ""

            print "Received query " + Major + ":" + Minor

            sql = "SELECT Picture FROM beaconinfo WHERE major=" + Major + " AND minor=" + Minor + ";"

            cursor.execute(sql)

            for row in cursor.fetchall():

                mess = row[0]
                msg = mess.encode('utf=8')


            self.message(msg)

    def message(self, message):
        self.transport.write(message + '\n')


factory = Factory()
factory.protocol = MessageServer
factory.clients = []

reactor.listenTCP(8080, factory)
print "Python message test server started"
reactor.run()

此代码发生的情况是,当应用程序查询服务器时,服务器发送回图像数据(以base64格式),应用程序接收此数据并触发switch语句的EventHasBytesAvailable情况。但是只显示了图像的一小部分,我得到一个错误日志:

<Error>: ImageIO: JPEG Corrupt JPEG data: premature end of data segment

这让我相信并非所有数据都来自流。你会在代码中看到我有一个NSLog说“收到的数据”#39;每次调用EventHasBytesAvailable案例并且&#39;显示图像&#39;当使用图像数据设置UIImageView时。

我发现奇怪的事情,我觉得这个问题的根源是当EventHasBytesAvailable被称为“收到的数据”时。记录消息,然后显示图像&#39;记录消息,然后再次记录“收到的数据”。记录消息,然后记录上面列出的错误。

所以看起来有一小部分数据通过流进入,循环收集这些字节并将它们粘贴在UIImageView中,然后更多字节通过流进入并尝试将它们放入UIImageView中但是数据段的过早结束了#9;发生错误。

我很困惑为什么会这样。不应该通过一次调用EventHasBytesAvailable案例来通过流发送图像的整个数据吗?可能我在代码中看了缓冲区?我的缓冲区可以拍摄60kb的图像吗?这是我能想到的唯一可能与应用程序代码相关的东西,然后我能想到的可能是Python脚本是以两个块而不是一个块发送数据。

感谢您的时间。我是一个实习生,用这个打了一个墙!任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

解决了这个问题。因此,该流正在多次调用“HasBytes”中发送数据。案件。所以我创建了一个字符串,当&#39; HasBytes&#39;时,它会附加每个数据块。被叫。我还使用了另一种方法将图像数据字符串转换为NSData对象。

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

// string property for appending
//            
_str = [_str stringByAppendingString:ImgStr];

NSData *ImgData = [[NSData alloc] initWithBase64EncodedString:_str options:1];


if (nil != ImgData)
{

     self.ImageView.image = [UIImage imageWithData:ImgData];

}

非常感谢!