In my app I doing something very similar to what is done in the WiTap project. I use Bonjour to discover peers and then send data over the socket to perform an initial handshake.
I'm able to see the data being sent OTA using Cocoa Packet Analyzer. But the stream: handleEvent: function is never called on the receiving peer side.
What I am able to see is:
Sometimes, when the peer that sent the data exits, the receiver peer seems to get the data.
Sometimes I am able to see an NSStreamEventErrorOccurred error in the handler function.
I'm unable to see any noticeable pattern on when the above behavior occurs.
Here is a bit of the code that might be helpful.
PacketSender and PacketReceiver objects are singletons.
I have verified multiple times that the correct (and the only) instance of these objects are set as delegates while debugging:
if (![netService getInputStream:&_inStream outputStream:&_outStream])
{
[Utilities showAlert:#"Failed connecting to server"];
return BM_ERROR_NETSERVICE_STREAM_FAIL;
}
if(!sharedProtocolManager.mPacketSender)
{
sharedProtocolManager.mPacketSender = [PacketSender sharedSender];
}
if(!sharedProtocolManager.mPacketReceiver)
{
sharedProtocolManager.mPacketReceiver = [PacketReceiver sharedReceiver];
}
if(!sharedProtocolManager.mPacketSender || !sharedProtocolManager.mPacketReceiver)
{
return BM_ERROR_FAIL;
}
[PacketReceiver setupInStream:_inStream];
[PacketSender setupOutStream:_outStream];
}
Inside the PacketReceiver setupInStream: function I have:
if (sharedPacketReceiver->mInStream != inStream)
{
[sharedPacketReceiver->mInStream release];
sharedPacketReceiver->mInStream = [inStream retain];
}
sharedPacketReceiver->mInStream.delegate = sharedPacketReceiver;
Any answers or even suggestions on ways to debug this further would be greatly appreciated.
Thanks!
Related
Is there a way to be aware of connection status with Prisma?
I understand it does everything automatically so I don't have to worry about anything related to connection.
But what if I want to?
Basically I miss two things:
Catchable event. Either client.on('disconnected', ...) or implementing an interface (e.g. onDisconnected() { ... })
$connect() throwing error if it can not connect. No exception raised when DB is not started and I start the application.
// Context:
// - DB not started yet
try {
await client.$connect();
console.log('DB connected');
} catch (e) {
console.log('DB is unavailable');
}
// Output
//
// > DB connected
My use case: I would like to send a system message to maintainers and shut the whole service down if the DB stopped and could not recover connection within a time frame.
Okay, I was able to overcome it. I guess it's rather a bug than a feature.
So $connect() does not throw error it could connect successfully before but the DB has been stopped meanwhile and $disconnect() was not called.
So, calling $disconnect() when lost connection is recognized resulted in $connect() throwing error if still not able to connect.
I still miss the ability to watch for connection events but this is enough for me now.
Is there a way to get a Clients IP in Context of a write?
I want to get the IP of an Client that writes to my Milo-OPCUA-Server, so I can handle these writes differently based on the Clients IP (local Clients should be able to write directly on the Server, whilst other writes should get forwarded to another Server)
Okay, this is not part of any official API right now, so it almost certainly will break in the future, but:
With the OperationContext you get when implementing AttributeManager#write(WriteContext, List<WriteValue>):
context.getSession().ifPresent(session -> {
UaStackServer stackServer = context.getServer().getServer();
if (stackServer instanceof UaTcpStackServer) {
ServerSecureChannel secureChannel = ((UaTcpStackServer) stackServer)
.getSecureChannel(session.getSecureChannelId());
Channel channel = secureChannel.attr(UaTcpStackServer.BoundChannelKey).get();
SocketAddress remoteAddress = channel.remoteAddress();
}
});
I'll have to add some official API to do this, probably something hanging off the Session object.
I Implemented a HttpListener to process SoapRequests. This works fine but I can't find a soloution for the problem, that some soap-requests take too much time, resulting in timeouts on client side.
How do I let the requesting client know, that his request is not a timeout?
I thought about sending "dummy"-information while the request gets processsed, but the HttpListener only seems to send the data when you Close the response-object, and this can be done only once, so this is not the right thing to do I suppose.
Soloution:
Thread alliveWorker = new Thread(() =>
{
try
{
while (context.Response.OutputStream.CanWrite)
{
context.Response.OutputStream.WriteByte((byte) ' ');
context.Response.OutputStream.Flush();
Thread.Sleep(5000);
}
}
finally
{
}
});
alliveWorker.Start();
doWork();
alliveWorker.Interrupt();
createTheRealResponse();
Sending dummy information is not a bad idea.
I think you need to call the Flush() method on the HttpListenerResponse's OutputStream property after writing the dummy data. You must also enable SendChunked property:
Try sending a dummy space at regular interval:
response.SendChunked = true;
response.OutputStream.WriteByte((byte)' ');
response.OutputStream.Flush();
I see two options - increase timeouts on client side or extend protocol with operation status requests from client for long running operations.
If you are using .net 4.5, take a look at the HttpListenerTimeoutManager Class, you can use this class as a base to implement custom timeout behaviour.
I am trying to Implement Banjour based application in ios. I implement success fully also sending and receiving data to one iphone to another iphone.
After browsing the services all other device in the work. and display in to the Table.
Now i want to select some devices in the table view, and send data to the selected devices
For that i created only one socket in each device.
CFSocketContext socketCtxt = {0, self, NULL, NULL, NULL};
witap_socket = CFSocketCreate(kCFAllocatorDefault, PF_INET6, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)&TCPServerAcceptCallBack, &socketCtxt);
if (witap_socket != NULL)
{
protocolFamily = PF_INET6;
}
else
{
witap_socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)&TCPServerAcceptCallBack, &socketCtxt);
if (witap_socket != NULL)
{
protocolFamily = PF_INET;
}
}
now i want to send data to the selected devices. for that I stored selected NSNetService(ie devices) another NSMutableArray. When used Click the send button particular Action will invoked.
-(void)SendActionFunction
{
for(int idx=0;idx<[selectedSer count];idx++)
{
NSNetService *service = [self.selectedSer objectAtIndex:idx];
NSLog(#"service......%#",[service name]);
self.currentResolve = [self.selectedSer objectAtIndex:idx];
[self.currentResolve setDelegate:self];
[self.currentResolve resolveWithTimeout:0.0];
}
}
if i am trying to Resolve address for each device(above code). It will resolve only for first device. and getting error
(Error code=-72003]
one more problem if i resolved address for a device it automatically remove from Tableview.
So my doubts are:
Why the selected device revoved?
Now i create TCP based socket, How to add destination address to send data?
Is it possible to send data from single socket to multiple destination?
As per Apple's definition, A CFSocket is a communications channel implemented with a BSD socket.
You have established a socket connection between the devices. But for sending and receiving data, you must make use of NSStreams. Documentation can be found here
I see you are using Apple's sample code Witap as the reference.
For sending and receiving the data, use NSStreamDelegate also.
What about resolve and send datas 1 device per 1 device ? Sounds easier :D
BTW, there is a really nice socket library I used for a project :
https://github.com/robbiehanson/CocoaAsyncSocket
I have a linux server program that waits for incoming connections from a client and depending on what command you send it performs a different connection. Here is the pseudo-code
setup_socket();
while(1)
{
listen();
newfile_descriptor = accept();
int command
read(newfile_descriptor,&command,sizeof(int));
switch(command)
{
...
}
}
But when I want to send more than one command with the same client it listens forever (since a new connection is not being made). Is there a way to check if there is already connection before listening to a new one?
How about a loop where you read the commands:
setup_socket();
while(1)
{
listen();
newfile_descriptor = accept();
int command
command = read(newfile_descriptor,&command,sizeof(int));
while(command) {
switch(command)
{
...
}
// get next command, or figure out closed connection
command = read(newfile_descriptor,&command,sizeof(int));
}
}
You either demultiplex the socket IO with select/poll, or have a separate thread read the commands on the client socket.
How about checking if you can read from the socket some more? I would think you should close your connection at the end of the command if there isn't anything more coming in.
What you need is some basic protocol which allows the client to inform you that it is done sending commands. It could be as simple as the client continues to send commands, then closes the socket when it no longer needs to send any more. In that case, you would simply continue to read from the socket until it is closed. In your pseudo code, it would look something like this:
setup_socket();
while(1) {
listen();
newfile_descriptor = accept();
int command;
do {
command = read(newfile_descriptor,&command,sizeof(int));
if (command > 0) {
switch(command) {
...
}
}
} while (command > 0);
}
To elaborate on Nikolai's response, check out the indispensable Beej's guides.
It is a very standard practice to spawn a new thread immediately after calling accept() inside of your while(1) loop; this thread handles all the communication with the client so that the main thread can continue listen()ing for new incoming connections and accept()ing when they arrive.
Here is the specific section on select(), which I know about, but haven't actually used before.
The very first thing...
Is to move your listen() outside the while loop.
:p