Can't broadcast message from ios app - iphone

I want to broadcast message in socket based ios app. I managed to create socket, bind, enable broadcasting, and turn on non-blocking, but when i try to broadcast meesage (sendto function), I receive -1, which indicates error. Anyone know why is this happening?
int service_port = xxxx;
NSString *rawMsg = #"xxx";
// Create a socket
int socketfd = socket( AF_INET, SOCK_STREAM, 0 );
struct sockaddr_in ip4addr;
ip4addr.sin_family = AF_INET;
ip4addr.sin_port = htons(service_port);
ip4addr.sin_addr.s_addr = inet_addr("0.0.0.0");
memset(ip4addr.sin_zero, '\0', sizeof ip4addr.sin_zero);
int ret = bind(socketfd, (struct sockaddr*)&ip4addr, sizeof ip4addr);
// Set socket options
// Enable broadcast
int broadcastEnable=1;
ret = setsockopt(socketfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
//turn non-blocking
ret = fcntl(socketfd, F_SETFL, O_NONBLOCK);
//udp broadcast
struct sockaddr_in address; // Make an endpoint
address.sin_family = AF_INET;
address.sin_port = htons(service_port);
address.sin_addr.s_addr = inet_addr("255.255.255.255");
memset(address.sin_zero, '\0', sizeof address.sin_zero);
ret = sendto(socketfd, (__bridge const void *)(rawMsg), strlen((__bridge const void *)(rawMsg)), 0, (struct sockaddr*)&address, sizeof address);
NSLog(#"result = %d", ret);

Related

TCP socket server using in6addr_any, the client can't connect use c, just using local ipv6

TCP socket server address using in6addr_any, the client can't connect
(using code 1), but using local ipv6 "fc00::2a4:1ff:fe15:7031", the client can connect (using code 2). The client and server are on two tasks of the same PC. Another pc can ping6 ipv6 "fc00::2a4:1ff:fe15:7031" successfully. But now, I just want to use code 1 instead of code 2 in the client.c and server.c on the same pc. What should I do?
a part code of server.c:
int ret = 0;
int fd;
unsigned int addrPort = tcp_port;
char addrIp[] = "fc00::2a4:1ff:fe15:7031";
fd = socket(AF_INET6, SOCK_STREAM, 0);
if( -1 == fd)
{
return -1;
}
memset_s(serv_addr, sizeof(struct sockaddr_in6), 0x0, sizeof(struct sockaddr_in6));
serv_addr->sin6_family = AF_INET6;
serv_addr->sin6_port = htons(7770);
serv_addr->sin6_len = sizeof(struct sockaddr_in6);
inet_pton(AF_INET6, addrIp, &serv_addr->sin6_addr);
// serv_addr->sin6_addr = in6addr_any;
ret = bind(fd, serv_addr, sizeof(struct sockaddr_in6));
if(0 != ret )
{
close(fd);
return -1;
}
ret = listen(fd, 1);
if(0 != ret )
{
close(fd);
return -1;
}
*server_fd = fd;
return VOS_OK;
code 1:
serv_addr->sin6_addr = in6addr_any;
code 2:
inet_pton(AF_INET6, addrIp, &serv_addr->sin6_addr);

UDP broadcast being sent, but not received (yes, again)

I have a question seemingly the same as this one, yet having checked that and others I can't see the difference.
I have an app that receives UDP broadcasts. It loops back on itself properly, and can on the same machine receive from another app. However, when I try to receive from an external GoPro Hero4 Black,
I can send and receive TCP with the camera within the same app
Another app on the same machine can receive the UDP broadcasts from the camera
This app sees nothing
I checked for properly using INADDR_ANY, and it's being done in the code. Given the machine does receive the packets, and the app itself can do TCP with the camera, the error has to be in the UDP receive code, yet that works between apps on the same machine.
Question: What could cause this behavior?
My belief is the problem is in my understanding of UDP broadcast receive, but nevertheless, in response to a comment, here's code. This initializes the receiver:
int yudpsocket_server(const char *addr,int port) {
//create socket
int socketfd=socket(AF_INET, SOCK_DGRAM, 0);
int reuseon = 1;
int r = -1;
//bind
struct sockaddr_in serv_addr;
serv_addr.sin_len = sizeof(struct sockaddr_in);
serv_addr.sin_family = AF_INET;
if (addr == NULL || strlen(addr) == 0 || strcmp(addr, BROADCAST_IP) == 0) {
r = setsockopt( socketfd, SOL_SOCKET, SO_BROADCAST, &reuseon, sizeof(reuseon) );
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
} else {
r = setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, &reuseon, sizeof(reuseon) );
serv_addr.sin_addr.s_addr = inet_addr(addr);
serv_addr.sin_port = htons(port);
memset( &serv_addr, '\0', sizeof(serv_addr));
}
if (r == -1) {
return -1;
}
r = bind(socketfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (r==0) {
return socketfd;
} else {
return -1;
}
}
And this does the receive:
int yudpsocket_receive(int socket_fd, char *outdata, int expted_len, char *remoteip, int* remoteport) {
struct sockaddr_in cli_addr;
socklen_t clilen = sizeof(cli_addr);
memset(&cli_addr, 0x0, sizeof(struct sockaddr_in));
int len = (int)recvfrom(socket_fd, outdata, expted_len, 0, (struct sockaddr *)&cli_addr, &clilen);
char *clientip = inet_ntoa(cli_addr.sin_addr);
memcpy(remoteip, clientip, strlen(clientip));
*remoteport = cli_addr.sin_port; // Maybe not right - s.b. ntohs()?
return len;
}

Pagefault when using recvfrom() in VxWorks

I have a weird problem with the posix socket api in vxworks 5.5.1. The code is trivial and probably not interesting (added below), but the gist of it is: When calling socket() and bind() in a separate function from the one calling recvfrom(), a pagefault occurs at the recvfrom() call. If everything is done in the same function it works fine. Note that the fault happens immediately when calling recvfrom(), not when a packet arrives.
Does VxWorks use the stack in some unexpected way for this API?
Edit: Added some code. The te_serve1() function works fine, but te_serve_one() (using helper functions) do not.
#include <taskLib.h>
#include <sysLib.h>
#include <string.h>
#include <taskLib.h>
#include <stdlib.h>
#include <stdio.h>
#include <types.h>
#include <sys/socket.h>
#include <sockLib.h>
#include <netinet/in.h>
#ifdef DEBUG
#define DP(...) printf(__VA_ARGS__)
#else
#define DP(...) do { } while(0)
#endif
#define LLB(l, b) ((l & (0x000000FF << (b*8))) >> b*8)
struct msg_log {
unsigned long src;
int size;
};
static int setup(short port)
{
int err = 0;
struct sockaddr_in addr;
int sock;
DP("socket()\n");
err = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (err < 0)
return err;
sock = err;
addr.sin_family = AF_INET;
addr.sin_port = htons(7357);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
DP("bind()\n");
err = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if (err) {
close(sock);
return err;
}
return sock;
}
static int serve(int sock, struct msg_log *log)
{
char buf[32];
struct sockaddr_in caddr;
int caddr_len = sizeof(caddr);
int ret;
int len;
bzero((char *)&caddr, sizeof(caddr));
DP("recvfrom()\n");
ret = recvfrom(sock, buf, sizeof(buf), 0,
(struct sockaddr *) &caddr, &caddr_len);
if (ret < 0) return ret;
len = ret;
if (log) {
DP("log()");
log->src = caddr.sin_addr.s_addr;
log->size = len;
}
DP("sendto()");
ret = sendto(sock, (caddr_t) &buf, len, 0, (struct sockaddr *) &caddr, caddr_len);
return ret;
}
static void serve_multiple(int sock)
{
for (;;)
if (serve(sock, NULL) < 0) break;
}
int te_serve_one(void)
{
DP("%s\n", __FUNCTION__);
int sock;
struct msg_log log; /* = {0}; */
int ret = 0;
short port = 1234;
DP("setup()\n");
sock = setup(port);
if (sock < 0)
goto out;
sock = ret;
ret = serve(sock, &log);
if(ret < 0)
goto tidy;
DP("report:\n");
printf("Echo'd %d byte to %lu.%lu.%lu.%lu\n",
log.size,
LLB(log.src, 0),
LLB(log.src, 1),
LLB(log.src, 2),
LLB(log.src, 3));
tidy:
DP("close()");
close(sock);
out:
return ret;
}
int te_serve1(short port)
{
int ret = 0;
int sock;
struct sockaddr_in addr;
char buf[32];
struct sockaddr_in caddr;
int caddr_len = sizeof(caddr);
int len;
DP("socket()\n");
ret = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ret < 0)
goto out;
sock = ret;
/* host addr */
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
DP("bind()\n");
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if (ret)
goto tidy;
/* serve */
for (;;) {
DP("recvfrom()\n");
ret = recvfrom(sock, buf, sizeof(buf), 0,
(struct sockaddr *) &caddr, &caddr_len);
if (ret < 0)
break;
len = ret;
if (len >= 4 && !strncmp(buf, "kill", 4)) {
ret = 0;
break;
}
DP("sendto()\n");
ret = sendto(sock, (caddr_t) &buf, len, 0,
(struct sockaddr *) &caddr, caddr_len);
printf("Echo'd %d byte to %lu.%lu.%lu.%lu\n",
len,
LLB(caddr.sin_addr.s_addr, 0), LLB(caddr.sin_addr.s_addr, 1),
LLB(caddr.sin_addr.s_addr, 2), LLB(caddr.sin_addr.s_addr, 3));
}
tidy:
DP("close()");
close(sock);
out:
return ret;
}
settup() declares following local:
struct sockaddr_in addr;
What happens if you declare "struct sockaddr_in addr;" in te_serve_one() and pass it to setup()?
Looking at the optimized assembly, I realized that the sock variable got overwritten by ret, which at that point is unused and initialized to zero. Splendid.

Bind failed with Invalid argument error

I'm trying to write a simple program which uses bind. The code compiles on solaris, but I get a bind() failed with Invalid Argument error.
I have tried many times but getting the same error, I'm unable to figure out the error.
Here is the code :
int my_func ()
{
struct sockaddr_storage name;
struct addrinfo hints, *res;
int status;
char hostnamestr[256];
gethostname (hostnamestr, 256);
int iRC;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(hostnamestr, NULL, &hints, &res) != 0))
{
printf("getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
memcpy(&name, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
monsocket = socket (name.ss_family, SOCK_STREAM, IPPROTO_TCP);
int iLastError = WSAGetLastError ();
if (monsocket == -1)
{
fprintf (stderr, "cannot open socket for monitors [%s]\n", wsaerror (iLastError));
return 1;
}
sockopts(monsocket);
int flags;
flags = fcntl (monsocket, F_GETFL);
iLastError = WSAGetLastError ();
if (flags < 0)
{
fprintf (stderr, "cannot get flags for socket [%s]\n", wsaerror (iLastError));
return 1;
}
iRC = fcntl (monsocket, F_SETFL, flags | O_NONBLOCK);
iLastError = WSAGetLastError ();
if (iRC == -1)
{
fprintf (stderr, "cannot set flags for socket [%s]\n", wsaerror (iLastError));
return 1;
}
int iPort;
if(name.ss_family == AF_INET)
{
((struct sockaddr_in *) &name)->sin_port = htons (8091);
}
else if(name.ss_family == AF_INET6)
{
((struct sockaddr_in6 *) &name)->sin6_port = htons (8091);
}
struct sockaddr_in* ipv = (struct sockaddr_in *) &name;
printf("connecting to addr: %s\n", inet_ntoa(ipv->sin_addr));
iRC = bind (monsocket, (struct sockaddr *) &name, sizeof (name));
iLastError = WSAGetLastError ();
if (iRC == -1)
{
close(monsocket);
monsocket=-1;
fprintf (stderr, "could not bind to port %d\n", iPort);
printf("Error %s",wsaerror (iLastError));
return 1;
}
else
{
fprintf (SCHED_SHOW_MSG, "bound on port %i\n", ntohs (iPort));
}
iRC = listen (monsocket, SOMAXCONN);
iLastError = WSAGetLastError ();
if (iRC == -1)
{
fprintf (stderr, "could not listen to socket [%s]\n", wsaerror (iLastError));
return 1;
}
return 0;
}
bind (monsocket, (struct sockaddr *) &name, sizeof (name))
Your sizeof(name) yields the size of the generic sockaddr_storage size. You need the size of sockaddr_in or sockaddr_in6.
In any case, you'd be better of by just using the stuff from getaddrinfo directly:
monsocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(monsocket, res->ai_addr, res->ai_addrlen);
In order to do that you'll have to move your freeaddrinfo(res) call.
i got same error. and later found that i created socket for AF_INET and was trying to bind using IPv6 address.

Socket not working for iPhone SDK 3.0+

My code was working absolutely fine before the launch of iPhone SDK 3.0 , I am using socket functions to send data and receive data. What changes must i make to make it compatible for 3.0+.
-(int)InitSocket:(int)nPort: (NSString*)sServer{
if(sServer == nil)
{
return -1;
}
m_nPort = nPort;
sServerAddress = sServer;
const char* pServer = nil;
pServer = [sServer cStringUsingEncoding:NSASCIIStringEncoding];
m_nSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in servAddr;
memset(&servAddr, 0 , sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(pServer);
servAddr.sin_port = htons(m_nPort);
pfd.fd = m_nSock;
pfd.events = POLLIN | POLLERR| POLLHUP | POLLNVAL;
pfd.revents = 0;
m_nTimeout = -1;
int f = fcntl(m_nSock, F_GETFL, 0);
fcntl(m_nSock, F_SETFL, f | O_NONBLOCK |O_NDELAY);
int opt = 1;
setsockopt(m_nSock, SOL_SOCKET, SO_KEEPALIVE, (const void*)&opt,(socklen_t)sizeof(opt));
struct timeval timeout;
fd_set wset;
FD_ZERO(&wset);
FD_SET(m_nSock, &wset);
timeout.tv_sec = 2;
timeout.tv_usec = 0;
return 0;
}
This Code for sending data
-(int)SendData:(size_t) nSize: (NSString*) buffer{
int nTotalSent = 0;
const char *pSend = [buffer cStringUsingEncoding:NSASCIIStringEncoding];
while(nTotalSent != nSize)
{
int nSent = send(m_nSock, (const void*)pSend+nTotalSent, nSize-nTotalSent, 0);
if(nSent == -1)
{
return nSent;
}
nTotalSent += nSent;
}
return nTotalSent;
}
Will the above code works in iPhone SDK 3.0+ , what changes i need to employ to make it work.
Thanks
You could start by properly checking for errors. All those functions that you use return an error code if something goes wrong and you will never know.