简体   繁体   English

GCDAsyncSocket 无法同时获取读取数据

[英]Not getting read data simultaneously GCDAsyncSocket

I have two service class here.我这里有两个服务类。 One is Host service and another is Join service class.一个是Host服务,另一个是Join服务类。 From the HostService I am publishing NetService.从 HostService 我发布 NetService。 In the JoinService I am using NetServiceBrowser for getting published service.在 JoinService 中,我使用 NetServiceBrowser 来获取已发布的服务。 Then successfully connected to that hosted service.然后成功连接到该托管服务。

HostService and JoinService both contains different GCDAsyncSocket objects. HostService 和 JoinService 都包含不同的 GCDAsyncSocket 对象。 Both sockets are ininilized with the main queue as below.两个套接字都与主队列 ininilized 如下。

socket = GCDAsyncSocket(delegate: self, delegateQueue: .main)

When connection accepted by host from join both sockets are successfully connected.当主机从 join 接受连接时,两个套接字都成功连接。 So now I am able to sending data to each other.所以现在我可以互相发送数据了。

Then I am sending data from any of one socket.然后我从一个套接字中的任何一个发送数据。 Consider here sending from the host socket.在这里考虑从主机套接字发送。 I am using the following code for writing data.我正在使用以下代码写入数据。 In the HostService class.在 HostService 类中。

func sendValue(str: String) {
        let size = UInt(MemoryLayout<UInt64>.size)
        let data = Data(str.utf8)
        hostSocket.write(data, withTimeout: -1.0, tag: 0)
        hostSocket.readData(toLength: size, withTimeout: -1.0, tag: 0)
}

Then I am getting call in sock:didWriteDataWithTag:tag which is GCDAsyncDelegate's method in the HostService.然后我在 sock:didWriteDataWithTag:tag 中得到调用,这是 HostService 中 GCDAsyncDelegate 的方法。

func socket(_ sock: GCDAsyncSocket, didWriteDataWithTag tag: Int) {
        let astr = "Host did write data on join port: \(sock.connectedPort)"
        print(astr)
        socketStatusCompletionBlock(astr,sock)
}

Now I am expecting that I should get call simultaneously in below method implemented in JoinService's GCDAsyncSocketDelegate method.现在我希望我应该在 JoinService 的 GCDAsyncSocketDelegate 方法中实现的以下方法中同时调用。

func socket(_ sock: GCDAsyncSocket, didRead data: Data, withTag tag: Int) {
        let str = String(decoding: data, as: UTF8.self)
        let astr = "Join did read \(str) with host port: \(sock.connectedPort)"
        print(astr)
        socketStatusCompletionBlock(astr, sock)
        inComingValueCompletionBlock(str)
 }

But I am not getting call simultaneously.但我不会同时接到电话。

Then when I am sending data from the JoinService same as HostService I am getting call first in “func socket(_ sock: GCDAsyncSocket, didRead data: Data, withTag tag: Int)” and got data which was sent from HostService before.然后,当我从与 HostService 相同的 JoinService 发送数据时,我首先在“func socket(_ sock: GCDAsyncSocket, didRead data: Data, withTag tag: Int)”中得到调用,并获得了之前从 HostService 发送的数据。

So in summary I am getting the data sent from the other socket in didRead method when I am writing data from the current socket.所以总而言之,当我从当前套接字写入数据时,我在 didRead 方法中获取了从另一个套接字发送的数据。

In edition it seems like same problem from reading it.在版本中,阅读它似乎是同样的问题。 But i am not getting it.但我不明白。 GCDAsyncSocket Client not reading until write GCDAsyncSocket 客户端不读取直到写入

I think the problem is in GCDAsyncSocket.m class.我认为问题出在 GCDAsyncSocket.m 类中。 There is function有功能

- (void)setupReadAndWriteSourcesForNewlyConnectedSocket:(int)socketFD{}

which is initialising these two dispatch_source_t queues as follows这是初始化这两个 dispatch_source_t 队列如下

readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socketFD, 0, socketQueue);

writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, socketFD, 0, socketQueue);

Now follow the path as below, and open source.h file.现在按照下面的路径,打开 source.h 文件。

source.h_path_img

Now search for dispatch_source_create现在搜索dispatch_source_create

source.h_path_function

Read the description from the function.阅读函数的描述。 It is as belows.如下。

@function dispatch_source_create @function dispatch_source_create

@abstract Creates a new dispatch source to monitor low-level system objects and automatically submit a handler block to a dispatch queue in response to events. @abstract 创建一个新的调度源来监视低级系统对象,并自动将处理程序块提交到调度队列以响应事件。

@discussion Dispatch sources are not reentrant. @discussion 调度源不可重入。 Any events received while the dispatch source is suspended or while the event handler block is currently executing will be coalesced and delivered after the dispatch source is resumed or the event handler block has returned.在调度源暂停或事件处理程序块当前正在执行时接收到的任何事件都将在调度源恢复或事件处理程序块返回后合并传递。

So, from the discussion i can say that when i am sending i am getting call in callback handler for readSource but, it is coalesced for while and it is delivering after dispatch source is resumed or the handler block has returned.因此,从讨论中我可以说,当我发送时,我正在调用 readSource 的回调处理程序,但是,它合并了一段时间,并且在调度源恢复或处理程序块返回后正在交付。

Now in my case GCDAsyncReadPacket must be initialised and pass with the GCDAsyncSockets delegate method, but first time i am not getting this GCDAsyncReadPacket object.现在在我的情况下,GCDAsyncReadPacket 必须初始化并通过 GCDAsyncSockets 委托方法传递,但我第一次没有得到这个 GCDAsyncReadPacket 对象。 It is initialised later when i will call handler of "writeSource" while writing from the same socket as described behaviour with dispatch_source_create above.稍后当我将调用“writeSource”的处理程序同时从与上面使用dispatch_source_create描述的行为相同的套接字写入时,它会被初始化。

So, finally i did manually initialised GCDAsyncReadPacket object rather than get it later.所以,最后我手动初始化了 GCDAsyncReadPacket 对象,而不是稍后再获取它。 And everything is working fine.一切正常。 Here is my source code.这是我的源代码。

https://github.com/Dhaval1094/DTSocketTicTacToe https://github.com/Dhaval1094/DTSocketTicTacToe

How about:怎么样:

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    // ... your code
    [sock readDataWithTimeout:timeout tag:tag];
}

I had the same issue and it works for me.我有同样的问题,它对我有用。

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

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