Skip to content

Instantly share code, notes, and snippets.

@jakob
Created January 29, 2023 13:37
Show Gist options
  • Save jakob/c47db8754ffb248b1cf9e5911e85f5f4 to your computer and use it in GitHub Desktop.
Save jakob/c47db8754ffb248b1cf9e5911e85f5f4 to your computer and use it in GitHub Desktop.
Objective-C class for sending data via UDP
//
// UDPClient.h
// ParticleCar
//
// Created by Jakob Egger on 06/11/2016.
// Copyright © 2016 Egger Apps. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface UDPClient : NSObject
@property uint16_t destPort;
@property NSString * __nullable destIP;
@property BOOL broadcast;
-(__nonnull instancetype)initWithDestinationIP:(NSString* __nonnull)destIP port:(uint16_t)destPort;
-(BOOL)sendMessage:(NSData* __nonnull)data error:(NSError* __null_unspecified * __nullable)error;
@end
//
// UDPClient.m
// ParticleCar
//
// Created by Jakob Egger on 06/11/2016.
// Copyright © 2016 Egger Apps. All rights reserved.
//
#import "UDPClient.h"
#import <sys/types.h>
#import <sys/uio.h>
#import <sys/socket.h>
#import <sys/un.h>
#import <sys/select.h>
#import <sys/time.h>
#import <netdb.h>
#import <unistd.h>
#include <arpa/inet.h>
@implementation UDPClient
-(instancetype)initWithDestinationIP:(NSString*)destIP port:(uint16_t)destPort;
{
self = [super init];
if (self) {
_destIP = destIP;
_destPort = destPort;
}
return self;
}
-(BOOL)sendMessage:(NSData*)data error:(NSError**)error;
{
struct sockaddr_in addr;
bzero(&addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_len = sizeof addr;
addr.sin_port = htons(self.destPort); // <-- doesn't really matter, not sending from receiver
inet_pton(AF_INET, self.destIP.UTF8String, &addr.sin_addr);
NSLog(@"sending to %@", self.destIP);
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock<0) {
if (error) {
*error = [NSError errorWithDomain:@"UDPClient" code:errno userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"socket() failed: %s", strerror(errno)]}];
}
return NO;
}
if (self.broadcast) {
int yes = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof yes) == -1) {
if (error) {
*error = [NSError errorWithDomain:@"UDPClient" code:errno userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"setsockopt() failed: %s", strerror(errno)]}];
}
close(sock);
return NO;
}
}
if (connect(sock, (struct sockaddr*)&addr, addr.sin_len) == -1) {
if (error) {
*error = [NSError errorWithDomain:@"UDPClient" code:errno userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"connect() failed: %s", strerror(errno)]}];
}
close(sock);
return NO;
}
int bytesSent = send(sock, data.bytes, data.length, 0);
if (bytesSent == -1) {
if (error) {
*error = [NSError errorWithDomain:@"UDPClient" code:errno userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"send() failed: %s", strerror(errno)]}];
}
close(sock);
return NO;
}
else if (bytesSent != data.length) {
if (error) {
*error = [NSError errorWithDomain:@"UDPClient" code:errno userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"Unexpected number of bytes sent (%d instead of %d", bytesSent, (int)data.length]}];
}
close(sock);
return NO;
}
close(sock);
return YES;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment