简体   繁体   中英

Not getting read data simultaneously GCDAsyncSocket

I have two service class here. One is Host service and another is Join service class. From the HostService I am publishing NetService. In the JoinService I am using NetServiceBrowser for getting published service. Then successfully connected to that hosted service.

HostService and JoinService both contains different GCDAsyncSocket objects. Both sockets are ininilized with the main queue as below.

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

When connection accepted by host from join both sockets are successfully connected. 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.

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.

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.

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.

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.

In edition it seems like same problem from reading it. But i am not getting it. GCDAsyncSocket Client not reading until write

I think the problem is in GCDAsyncSocket.m class. There is function

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

which is initialising these two dispatch_source_t queues as follows

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_path_img

Now search for dispatch_source_create

source.h_path_function

Read the description from the function. It is as belows.

@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.

@discussion Dispatch sources are not reentrant. 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.

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. 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.

So, finally i did manually initialised GCDAsyncReadPacket object rather than get it later. And everything is working fine. Here is my source code.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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