I'm trying to interrupt
[NSOutputstream write]
when the connection is lost.
However, it seems that it continues to block even though I close the stream using
[NSOutputstream close].
All I'm trying to achieve is reconnection when the server connection is lost.
I tried to schedule a NSTimer before the send call - What it does is close the stream if the send call did not manage to finish within the interval (Something like 5 seconds) but the close operation does not affect the stream at all. It continues to block. Sigh.
How can I implement a auto-reconnection to the server in case of disconnection?
The best thing to do with streams is to register them on the threads run loop using scheduleInRunLoop:forMode and deal with the delegate events which are raised telling you when there is capacity to write, when there is data to read and when there are errors.
This way you are efficiently interacting with the network stack and when you detect an error through the delegate events, you can reconnect and add the new streams to the run loop.
NB: Calling close will remove the stream from the run loop.
Related
I'm working on a freeRTOS project and the SAM4S Xplained Pro.
In a task called every x ms, I would like to:
initiate transmission of datas
extract data from a reception buffer (if an end of frame has been detected)
I'm wandering if there is a way to wake up this task not only periodically, but also when an end of frame has been detected ? And when this task is woken up by this event, only extraction of data would be performed, not the data transmission.
Is the best way consists in creating two tasks ? One for emission, other for reception.
I've not writen any code yet, I'm looking for some advices on how to deal with FreeRTOS and communication issues, as I'm a begginer in it...
You can have the task block on a stream buffer or message buffer (https://www.freertos.org/RTOS-stream-message-buffers.html) and have the interrupt send data to the buffer to unblock the task. Set the read timeout to the period at which you want to transmit, that way the task will unblock when either it is time to transmit again or when data has arrived. You can use https://www.freertos.org/xTaskCheckForTimeOut.html to adjust the timeout to account for any time already spent in the Blocked state (i.e. if the task initially blocks for 100ms, but data arrives after 40ms which causes the task to unblock, then adjust the next block time to 60ms before blocking again to make up the whole 100ms).
I cant really understand this event.
I'm hoping that it is called when the sending queue (or something similar internal structure) is done sending previously written packets.
Is it a correct assumption?
I'm working on a video streamer over Multipeer connectivity, and I want to use this property to decide if I should drop a camera frame (if there is no NSStreamEventHasSpaceAvailable), or I can submit it for NSOutputStream.
Imagine a BlueTooth connection, where I really need to drop a lot of camera frame, instead of submit every frame to NSStream.
The NSStreamEventHasSpaceAvailable event indicates that you can write (at least one byte!) to the stream without blocking. That does not mean that previously written data is completely
delivered to the other endpoint of the connection.
I'm working with NSStream to send and receive single characters over a network connection.
I instantiate the streams both for reading and for writing using CFStreamCreatePairWithSocketToCFHost(...).
The basic working mechanism to send and receive is working fine.
Now I want to create the NSStream only when I need to send or receive something (usually one time every 2 minutes). The first time I create the streams, send the packet, close it and everything work well. Next I try to recreate the NSStream (create a new socket and open the stream on it), the opening function don't work. Since I'm using netcat to test it, I see that when I close the stream using [NSStream close] method, the connection on the server is not closing. How can I force to close the socket? Or there's a better way to do what I'm trying to do?
Use CFWriteStreamSetProperty and CFReadStreamSetProperty to set kCFStreamPropertyShouldCloseNativeSocket to kCFBooleanTrue in order that the underlying socket is closed when the stream is closed.
I have problem suspending the current task being executed, I have tried to set NSOperationQueue setSuspended=YES for pausing and setSuspended=NO for resuming the process.
According to apple docs I can not suspend already executing task.
If you want to issue a temporary halt to the execution of operations, you can suspend the corresponding operation queue using the setSuspended: method. Suspending a queue does not cause already executing operations to pause in the middle of their tasks. It simply prevents new operations from being scheduled for execution. You might suspend a queue in response to a user request to pause any ongoing work, because the expectation is that the user might eventually want to resume that work.
My app needs to suspend the time taking upload operation in case of internet unavailability and finally resume the same operation once internet is available. Is there any work around for this? or I just need to start the currently executing task from zero?
I think you need to start from zero. otherwise two problems will come there. If you resume the current uploading you cant assure that you are not missed any packets or not. At the same time if the connection available after a long period of time, server may delete the data that you uploaded previously because of the incomplete operation.
Whether or not you can resume or pause a operation queue is not your issue here...
If it worked like you imagined it could (and it doesn't) when you get back to servicing the TCP connection it may very well be in a bad state, it could have timed out, closed remotely...
you will want to find out what your server supports and use the parts of a REST (or similar) service to resume a stalled upload on a brand new fresh connection.
If you haven't yet, print out this and put it on the walls of your cube, make t-shirts for your family members to wear... maybe add it as a screensaver?
I am currently building an App using CocoaAsyncSocket. I connect to a TCP server and read/write some data.
I create the socket using
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
When data is received, I use FMDB to save it into a database. Everything works fine, until I send the App to Background (using Homebutton), and then resuming to it. The UI is frozen and not responsive, the Debugger shows, that it is waiting at semaphore_wait_trap.
Don't use the main queue as an argument to the delegateQueue parameter. Use one of the global concurrent queues or a serial/parallel queue you create yourself.
Update: I just looked at the implementation for GCDAsyncSocket and now realize that the delegate queue and methods are fired async to the actual read/write operations, which happen on an internal queue, so my suggestion was either irrelevant (depending on what you're actually doing in the completion methods) or, at the very least, not pertinent to the problem you're having. I think what's happening is that the internal socket(s) are being closed, as per the iOS App Programming Guide. To wit:
Be prepared to handle connection failures in your network-based
sockets. The system may tear down socket connections while your app
is suspended for any number of reasons. As long as your socket-based
code is prepared for other types of network failures, such as a lost
signal or network transition, this should not lead to any unusual
problems. When your app resumes, if it encounters a failure upon
using a socket, simply reestablish the connection.
The GCDAsyncSocket class you're using has some methods which seem to be aimed at dealing with this, such as -autoDisconnectOnClosedReadStream, and I think you just need to add some code to handle the disconnection / connection re-establishment case.