AsynchronousSocketChannel.write ensures TCP ACK? - nio

Question regarding AsynchronousSocketChannel.write method
public final <A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
Does this method guarantee ACK is received before the handler is fired?
Or it just ensures the ByteBuffer is delivered to network driver of local machine?

Neither. It ensures that the data has been transferred into the socket send buffer. From there it goes asynchronously to the NIC and from there to the network.

Related

Packet forwarding event in Contiki

I am doing some work on worm-attack detection in RPL. In RPL, the communication between the clients might be multiple hops, with the packets going through many nodes.
However, only the receiver gets a tcpip_event on reception of the packet. The nodes that the route passes through do not get this event. Is there any way to detect the packet on the intermediate nodes?
You cannot get a notification or callback when a packet is forwarded. However, you can get a callback when a packet is received or sent by the lower layers.
In Contiki, use the function rime_sniffer_add for that. Check apps/powertrace/powertrace.c for an example.
In Contiki-NG the function has been renamed to netstack_sniffer_add.
Usage example:
Declare the sniffer like this, in the global scope:
RIME_SNIFFER(packet_sniffer, input_packet, output_packet);
Then add the sniffer from your code, once, at the start of the application execution:
rime_sniffer_add(&packet_sniffer);
The functions input_packet and output_packets are callbacks defined by you and can be used to examine the packets; for example, like this:
static void
input_packet(void)
{
int rssi = (int)packetbuf_attr(PACKETBUF_ATTR_RSSI);
printf("received a packet with RSSI=%d\n", rssi);
}

What is the order of the completion packets for WSASend() and WSARecv() in this case?

Say that I have two programs, a client and a server, and that I am running the client and the server on the same computer (so the speed is extremely fast), and say that the client socket's receive buffer is empty, and that the server will not send any data to the client except if the client told the server to do so.
Now in the client, I call WSASend() and then after it I call WSARecv():
WSASend(...); // tell the server to send me some data
WSARecv(...);
So in the code above, WSASend() is telling the server to send some data to the client (for example: the string "hello").
Now after some time, two completion packets will be placed in the completion port:
The first completion packet is for WSASend() (telling me that the data
has been placed in the client socket's send buffer).
The second completion packet is for WSARecv() (telling me that the data
has been placed in the buffer that I passed to WSARecv() when I
called it).
Now my question is: is it possible that the completion packet for WSARecv() be placed in the completion port before the completion packet for WSASend() (so when I call GetQueuedCompletionStatus() I will get the completion packet for WSARecv() first)?
you must never assume any order of completion packets you got. you must have independent from this knowledge - which is operation complete.
you must define some structure inherited from OVERLAPPED and it this structure place all data related to operation. including tag which describe type of operation. so when you extract pointer to OVERLAPPED from IOCP you cast it to this structure and will be know - are this for recv or send, connect or disconnect.. for example
class IO_IRP : public OVERLAPPED
{
//...
DWORD m_opCode;// `recv`, `send`, `dsct`, `cnct`
IO_IRP(DWORD opCode,...) : m_opCode(opCode) {}
VOID IOCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered)
{
// switch (m_opCode)
m_pObj->IOCompletionRoutine(m_packet, m_opCode, dwErrorCode, dwNumberOfBytesTransfered, Pointer);
delete this;
}
static VOID CALLBACK _IOCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
{
static_cast<IO_IRP*>(lpOverlapped)->IOCompletionRoutine(dwErrorCode, dwNumberOfBytesTransfered);
}
};
// recv
if (IO_IRP* Irp = new IO_IRP('recv', ..))
{
WSARecv(..., Irp);
...
}

How to inform via interrupt when a new message has been received, using AT-Commands +CNMA or +CNMI in GSM Modems?

I'm developing a winform program in which I need to send and receive SMS messages.
I have no problem sending SMS, but I don't know how to inform when a new message has been received via a GSM modem. I want to have an acknowledgement like an interrupt or event, when a new message has been received.
As far as I know I should work to at+CNMI or at+CNMA, but unfortunately I can't find an example or suitable reference for those. Furthermore, I need to know how to get delivery message or how to handle that?
AT+CNMI and AT+CNMA are standard AT commands defined in the spec 3GPP TS 27.005, available here.
For confirmation of successful delivery, see section 3.5.1 of this document which is the description for "Send message, +CMGS".
When you are defining new port in your connection to connect, you should get a data received trigger to it.
SerialPort port = new SerialPort();
//...
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
and in that trigger:
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
MessageBox.Show(sp.ReadExisting()); //Data received
}

How network event FD_WRITE is generated when using Event Driven Sockets?

I am working on newtwork event based socket application.
When client has sent some data and there is something to be read on the socket, FD_READ network event is generated.
Now according to my understanding, when server wants to write over the socket, there must be an event generated i.e. FD_WRITE. But how this message will be generated?
When there is something available to be read, FD_READ is automatically generated but what about FD_WRITE when server wants to write something?
Anyone who can help me with this confusion please?
Following is the code snippet:
WSAEVENT hEvent = WSACreateEvent();
WSANETWORKEVENTS events;
WSAEventSelect(newSocketIdentifier, hEvent, FD_READ | FD_WRITE);
while(1)
{ //while(1) starts
waitRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE, WSA_INFINITE, FALSE);
//WSAResetEvent(hEvent);
if(WSAEnumNetworkEvents(newSocketIdentifier,hEvent,&events) == SOCKET_ERROR)
{
//Failure
}
else
{ //else event occurred starts
if(events.lNetworkEvents & FD_READ)
{
//recvfrom()
}
if(events.lNetworkEvents & FD_WRITE)
{
//sendto()
}
}
}
FD_WRITE means you can write to the socket right now. If the send buffers fill up (you're sending data faster than it can be sent on the network), eventually you won't be able to write anymore until you wait a bit.
Once you make a write that fails due to the buffers being full, this message will be sent to you to let you know you can retry that send.
It's also sent when you first open up the socket to let you know it's there and you can start writing.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms741576(v=vs.85).aspx
The FD_WRITE network event is handled slightly differently. An
FD_WRITE network event is recorded when a socket is first connected
with a call to the connect, ConnectEx, WSAConnect, WSAConnectByList,
or WSAConnectByName function or when a socket is accepted with accept,
AcceptEx, or WSAAccept function and then after a send fails with
WSAEWOULDBLOCK and buffer space becomes available. Therefore, an
application can assume that sends are possible starting from the first
FD_WRITE network event setting and lasting until a send returns
WSAEWOULDBLOCK. After such a failure the application will find out
that sends are again possible when an FD_WRITE network event is
recorded and the associated event object is set.
So, ideally you're probably keeping a flag as to whether it's OK to write, right now. It starts off as true, but eventually, you get a WSAEWOULDBLOCK when calling sendto, and you set it to false. Once you receive FD_WRITE, you set the flag back to true and resume sending packets.

Multi-clients on a server

For an application in C, i need to response more than one clients.
I setup the connection with a code like,
bind(...);
listen(...);
while(1){
accept(...);//accept a client
recv(...);//receive something
send(...);//send something to client
bzero(buf);//clear buffer
}
This works great when i have only one client. Other clients also can connect to the server but although they command something, server does not response back to clients who connected after the first client. How can i solve this problem?
Write a server using asynchronous, nonblocking connections.
Instead of a single set of data about a client, you need to create a struct. Each instance of the struct holds the data for each client.
The code looks vaguely like:
socket(...)
fcntl(...) to mark O_NONBLOCK
bind(...)
listen(...)
create poll entry for server socket.
while(1) {
poll(...)
if( fds[server_slot].revents & POLLIN ) {
accept(...)
fcntl(...) mark O_NONBLOCK
create poll and data array entries.
}
if( fds[i].revents & POLLIN ) {
recv(...) into data[i]
if connection i closed then clean up.
}
if( fds[i].revents & POLLOUT ) {
send(...) pending info for data[i]
}
}
If any of your calls return the error EAGAIN instead of success then don't panic. You just try again later. Be prepared for EAGAIN even if poll claims the socket is ready: it's good practice and more robust.
i need to response more than one clients.
Use Threading.
Basically you want your main thread to only do the accept part, and then handle the rest to another thread of execution (which can be either a thread or a process).
Whenever your main thread returns from "accept", give the socket descriptor to another thread, and call accept again (this can be done with fork, with pthread_create, or by maintaining a thread pool and using synchronization, for instance condition variables, to indicate that a new client has been accepted).
While the main thread will handle possible new clients incoming, the other threads will deal with the recv/send.

Resources