iPhone does not receive UDP data over WiFi - iphone

With a WiFi connection, UDP data is not received. It stops at:
recvfrom(sock, buf, RECV_BUF_SIZE, 0, (SOCKADDR*)&rAddr, (SOCK_LEN*)&len);
When I run the same program in iPhone simulator over ethernet it works well. What am I missing?

Look at the man page.
Like so:
recvfrom(mSock,recvBuff,1024,0,(struct sockaddr *)&from, &fromlen);
providing the parameter values you are setting are correct try this in your case try:
recvfrom(sock, buf, RECV_BUF_SIZE, 0, (struct sockaddr *)&rAddr, &len);

Related

Unix Domain Sockets datagram client with receive only

I have a simulator application which Unix Domain datagram sockets, which sends data to socket path for.ex /var/lib/XYZ.
sendto is returning -2 which is due to other end no peer is there(no other unix domian socket application is running)
I would like to write a datagram client/peer application using Unix Domain Sockets for receiving data from the server/simulator(which is sending data to /var/lib/XYZ).
My code is as follows:
#define BUF_SIZE 1024
#define SV_SOCK_PATH "/var/lib/XYZ"
#define SV_SOCK_PATH2 "/var/lib/ABC"
creation of Unix Domain sockets as below:
struct sockaddr_un svaddr, claddr;
....
sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sfd == -1)
printf("socket creation failed");
memset(&claddr, 0, sizeof(struct sockaddr_un));
claddr.sun_family = AF_UNIX;
strncpy(claddr.sun_path, SV_SOCK_PATH2, sizeof(claddr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &claddr, sizeof(struct sockaddr_un)) == -1)
printf("bind failed");
/* Construct address of server */
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);
while(1)
{
int len=sizeof(struct sockaddr_un);
numBytes = recvfrom(sfd, resp, BUF_SIZE, 0, (struct sockaddr*)&svaddr,&len);
if (numBytes == -1)
printf("recvfrom error");
else{
printf("no of bytes received from server: %d",(int)numBytes);
printf("Response %d: %s\n", (int) numBytes, resp);
}
}
remove(claddr.sun_path);
//exit(EXIT_SUCCESS);
}
but the program is not receiving anything...is there anything missed out??
When it comes to datagrams, there is no real client or server. Either side attempting to send is responsible for addressing datagrams to the other. So, in your code, the setup is all wrong. You're apparently attempting to direct the "server" (but really not a server, just the other peer) to send to you via svaddr but that isn't how it works.
For a datagram AF_UNIX socket, the sender either needs to explicitly specify the receiver's address in a sendto call, or it needs to first connect its socket to the receiver's address. (In the latter case, it can then use send instead of sendto since the peer address has been specified via connect.)
You can't specify the sending peer's address in the recvfrom call. The socket address argument in the recvfrom is intended to return to you the address from which the datagram was sent. Whatever is in that variable will be overwritten on successful return from recvfrom.
One way datagram peer programs are often structured: the "server" creates a well-known path and binds to it, then a "client" creates its own endpoint and binds to it (constructing a unique socket address for itself), then the client can sendto the server's well-known socket. The server, by using recvfrom to obtain the client's address along with the datagram, can then use sendto along with the address to return a message to the client (without needing to connect its socket). This provides a sort of client-server paradigm on top of the fundamentally equal-peer orientation of the datagram socket.
Finally, I should mention that it's usually a good idea to use fully specified pathnames to ensure both peers are using the same address even if started from different directories. (Normally, with AF_UNIX, the address is a path name in the file system used to "rendezvous" between the two peers -- so without a full path "some_socket" is "./some_socket" in the current working directory. Some systems, such as linux, also support an abstract "hidden" namespace that doesn't require a full path, but you must use an initial null byte in the name to specify that.)

how do a client knows that the server closed its socket

I am using the following client code. After a successful connect(), if server shuts down all its connections , how will my client knows about this server shutdown ? Is there any way to listen for this kind of events from client side code?
int sfd = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
struct sockaddr_in isa = getipa("localhost", 1025);
connect(sfd, (struct sockaddr*)&isa, sizeof isa);
ssize_t size = recv(sfd, (void*)buff, sizeof buff, MSG_WAITALL);
puts(buff);
printf("Enter message to send\n");
scanf("%s",sendMsg);
send(sfd, (void*) sendMsg, 255, MSG_NOSIGNAL)
recv() returns zero if this connection has been closed by the peer, or -1 with an errno setting if the connection has encountered an error.
This is documented.
You don't care about the other connections.
You could also consider adding error checking to the rest of your code. Every one of those system calls can encounter an error.

Will IPv6 addresses work in IPv4 mode?

I'm working on migrating some code from IPv4 only to IPv6, and of course I need to retain backwards compatibility for IPv4.
I have read through some documents and guides for converting my code, and have seen it written that using many of the newer APIs (like inet_pton() instead of inet_addr()) will just work in both IPv4 and IPv6.
However, in some cases it still isn't clear when I need to write code to handle each protocol in a different way. Specifically, I don't know whether a IPv6 address (family AF_INET6 using sockaddr_storage structure) will work on a local network.
So for example, let's say I create such an address using the built in constant in6addr_loopback, and then I try to use that for a parameter to a bind() call.
Will this work in both IPv4 and IPv6, or I need to create the right address type (AF_INET vs AF_INET6) for each case? Does it matter whether I am connecting to a local socket (i.e. the loopback as in this case) as opposed to a socket on an external device?
My client code is running on iPhone/iPad hardware in case it matters.
Every interface will derive a link local ipv6 address using mac address. This address is sufficient for communication within local network.
Regarding creation of socket, you need to specify the family (AF_INET and AF_INET6) and initialize and bind it.
IPv4:
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
IPv6:
struct sockaddr_in6 serv_addr, cli_addr;
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
serv_addr.sin6_family = AF_INET6;
serv_addr.sin6_addr = in6addr_any;
serv_addr.sin6_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
hope this helps!

how should I send messages from server to client in WinSock's UDP?

I am learning WinSock UDP. Most tutorials I've seen ask me to:
On server side:
SOCKET socked = socket(PF_INET, SOCK_DGRAM, 0)
bind(...);
for(;;) { recvfrom(..); }
On client side:
SOCKET socked = socket(PF_INET, SOCK_DGRAM, 0);
sendto(...);
But I wonder how can I do other way, send data from server to client. I don't know client's port (I figured out it vary every sendto call), and I want to be able to connect client behihd NAT to server and still recive data from server.
How it is done in modern games?
There are two questions in there.
Finding the address
The function recvfrom is declared:
int recvfrom(
__in SOCKET s,
__out char *buf,
__in int len,
__in int flags,
__out struct sockaddr *from, /* <--- */
__inout_opt int *fromlen /* <--- */
);
So you can use from and fromlen in sendto.
sendto(..., (SOCKADDR *)from, *fromlen);
NAT
The NAT-box should automatically allow the server to "answer" to the datagram sent by the client. So, the mere fact that the client sent a datagram causes the NAT-box to ephemerally (a few minutes?) open a port to allow traffic return.

sendto not working on VxWorks

I asked this question before and had no resolution (still having the problem). I am stumped because the function returned without error and NO DATA was sent! This code works on Linux ... the VxWorks version does not work (sendto does not send, though it returns without an ERROR).
The synopsis - I am writing a simple echo server - The server successfully receives
the data (from an x86 box) and claims it successfully SENT it back.
However NO DATA is received on the client (netcat on an x86). This
code is running on VxWorks 5.4 on a PowerPC box ...
I is the UDP data being buffered somehow?
Could another task be preventing sendto from sending? (NOT to get off on a wild goose chase here, but I taskspawn my application with a normal priority, i.e. below critical tasks like the network task etc etc ... so this is fine).
Could VxWorks be buffering my UDP data?
I HAVE setup my routing table ... pinging works!
There is NO firewall AFAIK ...
What are the nuances of sendto and what would prevent my data from
reaching the client ...
while(1)
{
readlen = recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &client_address, &slen);
if (readlen == ERROR)
{
printf("RECVFROM FAILED()/n");
return (ERROR);
}
printf("Received %d bytes FROM %s:%d\nData: %s\n\n",
readlen, inet_ntoa(client_address.sin_addr),
ntohs(client_address.sin_port), buf);
// Send it to right back to the client using the open UDP socket
// but send it to OUTPORT
client_address.sin_port = htons(OUTPORT);
// Remember slen is a value (not an address ... in, NOT in-out)
sendlen = sendto(sock, buf, BUFLEN, 0, (struct sockaddr*)&client_address, slen);
// more code ....
}
I trust ERROR is defined as -1, right? Then are you checking the return value of the sendto(2) call? What about the errno(3) value?
One obvious problem I see in the code is that you give BUFLEN as length of the message to be sent, while it should actually be readlen - the number of bytes you received.