- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我已经在 iPhone 和 Mac 之间设置了 Bonjour 网络。
用户在 Mac 中呈现的表格中选择 iPhone 的网络服务,并在两侧创建并打开一对流。
iPhone 首先向 Mac 发送代码(整数)。 Mac成功接收。
在用户输入和处理暂停后,Mac 开始向 iPhone 发送代码:
NSInteger bytesWritten = [self.streamOut write:buffer maxLength:sizeof(uint8_t)];
// bytesWritten is 1.
但是 iPhone 永远不会收到 NSStreamEventHasBytesAvailable 事件。在此之前我仔细检查了一下,iPhone 的 NSInputStream 上的 streamStatus 是 2,也就是 NSStreamStatusOpen,它应该是。
任何想法可能是错误的?
更新:我进行了一项测试,其中 Mac 是第一个向 iPhone 发送整数的人。同样,我从 Mac 的输出流中得到了 1 的 bytesWritten,但 iPhone 从未得到 NSStreamEventHasBytesAvailable 事件。
所以一定是iPhone的输入流出了问题。但我仔细检查过:
下面是用于创建 iPhone 输入流的代码。它使用 CF 类型,因为它是在 C 风格的套接字回调函数中完成的:
CFReadStreamRef readStream = NULL;
CFStreamCreatePairWithSocket(kCFAllocatorDefault, socketNativeHandle, &readStream, NULL);
if (readStream) {
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
server.streamIn = (NSInputStream *)readStream;
server.streamIn.delegate = server;
[server.streamIn scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
if ([server.streamIn streamStatus] == NSStreamStatusNotOpen)
[server.streamIn open];
CFRelease(readStream);
}
更新 2:信息响应阿拉斯泰尔的评论:
套接字选项
retain、release 和 copyDescription 回调设置为 NULL。 optionFlags 设置为 acceptCallback。
套接字创建
这是用于在 iPhone 和 Mac 上设置套接字的方法,以及我试图弄清楚这段代码中实际发生了什么的评论,该代码改编自各种教程和实验(有效):
/**
Socket creation, port assignment, socket scheduled in run loop.
The socket represents the port on this app's end of the connection.
*/
- (BOOL) makeSocket {
// Make a socket context, with which to configure the socket.
// It's a struct, but doesn't require "struct" prefix -- because typedef'd?
CFSocketContext socketCtxt = {0, self, NULL, NULL, NULL}; // 2nd arg is pointer for callback function
// Make socket.
// Sock stream goes with TCP protocol, the safe method used for most data transmissions.
// kCFSocketAcceptCallBack accepts connections automatically and presents them to the callback function supplied in this class ("acceptSocketCallback").
// CFSocketCallBack, the callback function itself.
// And note that the socket context is passed in at the end.
self.socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)&acceptSocketCallback, &socketCtxt);
// Do socket-creation error checking.
if (self.socket == NULL) {
// alert omitted
return NO;
}
// Prepare an int to pass to setsockopt function, telling it whether to use the option specified in arg 3.
int iSocketOption = 1; // 1 means, yes, use the option
// Set socket options.
// arg 1 is an int. C-style method returns native socket.
// arg 2, int for "level." SOL_SOCKET is standard.
// arg 3, int for "option name," which is "uninterpreted." SO_REUSEADDR enables local address reuse. This allows a new connection even when a port is in wait state.
// arg 4, void (wildcard type) pointer to iSocketOption, which has been set to 1, meaning, yes, use the SO_REUSEADDR option specified in arg 3.
// args 5, the size of iSocketOption, which can now be recycled as a buffer to report "the size of the value returned," whatever that is.
setsockopt(CFSocketGetNative(socket), SOL_SOCKET, SO_REUSEADDR, (void *)&iSocketOption, sizeof(iSocketOption));
// Set up a struct to take the port assignment.
// The identifier "addr4" is an allusion to IP version 4, the older protocol with fewer addresses, which is fine for a LAN.
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(addr4));
addr4.sin_len = sizeof(addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = 0; // this is where the socket will assign the port number
addr4.sin_addr.s_addr = htonl(INADDR_ANY);
// Convert to NSData so struct can be sent to CFSocketSetAddress.
NSData *address4 = [NSData dataWithBytes:&addr4 length:sizeof(addr4)];
// Set the port number.
// Struct still needs more processing. CFDataRef is a pointer to CFData, which is toll-free-bridged to NSData.
if (CFSocketSetAddress(socket, (CFDataRef)address4) != kCFSocketSuccess) {
// If unsuccessful, advise user of error (omitted)…
// ... and discard the useless socket.
if (self.socket)
CFRelease(socket);
self.socket = NULL;
return NO;
}
// The socket now has the port address. Extract it.
NSData *addr = [(NSData *)CFSocketCopyAddress(socket) autorelease];
// Assign the extracted port address to the original struct.
memcpy(&addr4, [addr bytes], [addr length]);
// Use "network to host short" to convert port number to host computer's endian order, in case network's is reversed.
self.port = ntohs(addr4.sin_port);
printf("\nUpon makeSocket, the port is %d.", self.port);// !!!:testing - always prints a 5-digit number
// Get reference to main run loop.
CFRunLoopRef cfrl = CFRunLoopGetCurrent();
// Schedule socket with run loop, by roundabout means.
CFRunLoopSourceRef source4 = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
CFRunLoopAddSource(cfrl, source4, kCFRunLoopCommonModes);
CFRelease(source4);
// Socket made
return YES;
}
Runloop 调度
是的,所有 4 个流都在运行循环中安排,都使用与我在上面的第一次更新中发布的代码相同的代码。
Runloop 阻塞:
我没有对同步、多线程、NSLocks 等做任何花哨的事情。如果我设置一个按钮操作来将某些内容打印到控制台,它会自始至终都有效——runloop 似乎在正常运行。
Update4,流端口?
Noa 的调试建议给了我进一步检查流属性的想法:
NSNumber *nTest = [self.streamIn propertyForKey:NSStreamSOCKSProxyPortKey]; // always null!
我曾假设流卡在它们的端口上,但令人惊讶的是,nTest
始终为空。它在我的应用程序中为空,这似乎指出了一个问题——但它在有效的教程应用程序中也是空的。如果流在创建后不需要卡在其端口分配上,那么端口属性的用途是什么?
也许端口属性不能直接访问?但是 nTest
在以下内容中也始终为 null:
NSDictionary *dTest = [theInStream propertyForKey:NSStreamSOCKSProxyConfigurationKey];
NSNumber *nTest = [dTest valueForKey:NSStreamSOCKSProxyPortKey];
NSLog(@"\tInstream port is %@.", nTest); // (null)
nTest = [dTest valueForKey:NSStreamSOCKSProxyPortKey];
NSLog(@"\tOutstream port is %@.", nTest); // (null)
最佳答案
问题出在这一行:
CFStreamCreatePairWithSocket(kCFAllocatorDefault, socketNativeHandle, &readStream, NULL);
如果我只在 iPhone 端接收数据,这就没问题了。但是我正在创建一对 流,而不仅仅是一个输入流,所以在这段代码下面我正在创建一个写入流:
CFStreamCreatePairWithSocket(kCFAllocatorDefault, socketNativeHandle, NULL, &writeStream);
CFStream Reference 说,“如果你传递 NULL [for readStream],这个函数将不会创建一个可读流。”它并没有说如果你传递 NULL,你将呈现一个以前创建的流不可操作。但这显然是发生了什么。
此设置的一个奇怪问题是,如果我首先打开 streamIn,我会遇到相反的问题:iPhone 会获得 hasByteAvailable 事件,但绝不会获得 hasSpaceAvailable 事件。正如问题中所述,如果我查询流的状态,两者都会返回 NSStreamStatusOpen。所以花了很长时间才弄清楚真正的错误在哪里。
(这个顺序流的创建是我几个月前建立的一个测试项目的一个产物,在这个项目中我测试了仅在一个方向或另一个方向上移动的数据。)
解决方案
两个流应该在一行中成对创建:
CFStreamCreatePairWithSocket(kCFAllocatorDefault, socketNativeHandle, &readStream, &writeStream);
关于ios - bytesWritten,但其他设备从未收到 NSStreamEventHasBytesAvailable 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10378001/
iphone设备UDID、iphone设备ID和iphone设备Token之间有什么区别? 通常,当我们使用苹果推送通知服务时,会使用 iPhone 设备 token 。 但我的目标只是识别唯一的 i
我们使用 firebase 从服务器向 Android 和 IOS 设备发送通知,并且我们使用旧版 FCM 发送通知。但是当我们的应用程序在后台时,通知由系统本身处理,因此我们无法通过应用程序处理它。
在 Google 上搜索后,我发现人们说只能通过“MFi 程序”将 iOS 设备与非 iOS 设备连接起来。这是真的吗? 我的项目主要集中于直接通过蓝牙与Arduino设备发送和接收信息。 iOS和非
所以我有一个通用应用程序,我正在设置 UIScrollView 的内容大小。显然,iPhone 和 iPad 上的内容大小会有所不同。如何为 iPad 设置某种尺寸,为 iPhone 和 iPod t
问题:如何在 pod 中使用连接到主机的原始设备作为 block 设备。 我尝试使用类型为“BlockDevice”的“hostPath” volumes: - my-data: hostPath
Implemented GCKDeviceScannerListener Singleton Class on ViewController, however its delegate methods
我有一个 (PhoneGap) 应用程序,它将成功获得 Passbook 通行证,并且还将成功接收与 Passbook 分开的推送通知(当伪造设备 ID 时)。 我遇到的问题是发送给注册设备的设备 I
我正在尝试找到一种方法,通过我目前正在使用的 iOS 应用程序访问我的信标的电池电量。我正在使用 Kontakt 的 iBeacon 设备。我浏览了 Estimote iOS SDK,他们提供了一种实
我正在努力让 CUDA 应用程序也能监控 GPU 的核心温度。可通过 NVAPI 访问该信息。 问题是我想确保在运行代码时监控的是同一个 GPU。 但是,似乎有信息表明我从 NvAPI_EnumPhy
从沙箱模式到生产模式,设备 token 有何不同? 我认为我已将一些设备 token 锁定为生产模式,并且无法将它们从开发中插入。 关于如何检查有什么想法吗? 最佳答案 当您使用开发证书构建应用程序时
目录 /run/user/1000/gvfs 和 ~/.gvfs 分别是空的和不存在的。我的图形文件管理器 (Thunar) 能够检测和访问设备的内部和外部存储器。 命令 gvfs-mount -l
我有一个 Android 平板电脑,它有一个迷你 USB 端口和一个 USB 端口,我想编写一个与 USB key 通信的应用程序。我写了一个demo来找出U盘,但是没有任何反应。 令我不安的是,如果
我们将 PHP 版本从 5.4.25 更改为 5.4.45,并在服务器上安装了 MS SQL 驱动程序。在更改服务器之前,一切正常,但在更改服务器之后,我遇到了 Web 服务问题。我们的身份验证 So
我想知道是否有人使用此 API 在 Android 设备上同时从 2 个后置摄像头捕获图像或视频:https://source.android.com/docs/core/camera/concurr
我正在为客户构建一个物联网解决方案,网络管理员坚持要求设备仅通过访客网络进行连接,该网络有一个强制门户,其中的服务条款必须通过按下 UI 按钮来接受,然后才能获得外部互联网访问。到目前为止,我见过的大
我无法弄清楚这里的格式规则..在我的示例中,代码行太多,无法为每行添加 4 个空格,因此这里是我需要帮助的代码的链接 http://nitemsg.blogspot.com/2011/01/heres
如果我在我的设备上接受推送通知,并且不保存设备 token ,那么我如何在自定义 View 中查看设备 token 或恢复警报 View ? 我删除了应用程序并重新安装,但看不到设备 token 警报
我试图找出在尝试并行比较和复制设备 block 与 pthreads 时我做错了什么。看起来我正在脱离同步并且比较阶段无法正常工作。任何帮助将不胜感激 #ifndef __dbg_h__ #defin
我刚刚写完所有这些内容,但这个红色的小栏告诉我我不能发布图片或两个以上的链接。因此,如果您可以引用 this Imgur album , 那简直太好了。谢谢。 我在这里相对较新,甚至对 android
我需要启用 mysql 常规日志并将其通过 nsf 移动到我系统中的另一个驱动器/设备! 所以,我在 my.cnf 中启用了它: general_log = 1 general_log_fi
我是一名优秀的程序员,十分优秀!