This is my Client and Server code for CFSocket communication but on successful connection this code crashes.
Client.m
-(void)createConnection
{
CFSocketContext socketContext = {0,(__bridge void *)(self),NULL,NULL,NULL};
_socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketConnectCallBack,(CFSocketCallBack)kCFSocketConnectCallBack, &socketContext);
if (_socket != nil) {
struct sockaddr_in addr4;
memset (& addr4, 0, sizeof (addr4));
addr4.sin_len = sizeof (addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons (8888);
NSString *strAddress = #"xxx.xxx.x.xxx";
addr4.sin_addr.s_addr = inet_addr ([strAddress UTF8String]);
CFDataRef address = CFDataCreate (kCFAllocatorDefault, (UInt8 *) & addr4, sizeof (addr4));
CFSocketConnectToAddress (_socket,address,-1);
CFSocketEnableCallBacks(_socket, kCFSocketConnectCallBack);
CFRunLoopRef cRunRef = CFRunLoopGetCurrent ();
CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource (kCFAllocatorDefault, _socket, 0);
CFRunLoopAddSource (cRunRef,sourceRef,kCFRunLoopCommonModes);
char ethadd []= "helloworld";
CFDataRef Data = CFDataCreate(NULL, (const UInt8*)ethadd, sizeof(ethadd));
int socket_error = CFSocketSendData (_socket, (CFDataRef) address, (CFDataRef) Data, 10);
if (socket_error < 0){
NSLog(#"Data could not be sent!");
// return EXIT_FAILURE;
}
else NSLog(#"Data Sent");
CFRelease (sourceRef);
}
}
void TCPServerConnectCallBack (CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void * data, void * info) {
if (data != NULL) {
// When the socket is kCFSocketConnectCallBack failure callback failed to return an error code pointer, other returns NULL
NSLog (#"connection failed");
return;
}
Client * client = (__bridge Client *) info;
[client readStream];
}
- (void)readStream {
char buffer [1024];
while (recv (CFSocketGetNative (_socket), // ??Socket associated with the authority has failed to return -1: INVALID_SOCKET is
buffer, sizeof (buffer), 0)) {
NSLog (#"%#", [NSString stringWithUTF8String: buffer]);
}
}
- (void) SendMessage :(NSString *)text {
// [self createConnection];
NSString * stringTosend = text;
char * data = (char *)[stringTosend UTF8String];
send (CFSocketGetNative (_socket), data, strlen (data) + 1, 0);
}
Server.m
-(void)setupSocket
{
setupSocket();
}
int setupSocket () {
_socket = CFSocketCreate (kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)kCFSocketAcceptCallBack, NULL);
if (NULL == _socket) {
NSLog (# "Cannot create socket!");
return 0;
}
int optval = 1;
setsockopt (CFSocketGetNative (_socket), SOL_SOCKET, SO_REUSEADDR, // ??allow reuse of local address and port
(void *) & optval, sizeof (optval));
struct sockaddr_in addr4;
memset (& addr4, 0, sizeof (addr4));
addr4.sin_len = sizeof (addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons (8888);
addr4.sin_addr.s_addr = inet_addr ([#"xxx.xxx.x.xxx" UTF8String]);//htlon(INADDR_ANY)
CFDataRef address = CFDataCreate (kCFAllocatorDefault, (UInt8 *) & addr4, sizeof (addr4));
if (kCFSocketSuccess != CFSocketSetAddress (_socket, address)) {
NSLog (# "Bind to address failed!");
if (_socket)
CFRelease (_socket);
_socket = NULL;
return 0;
}
CFSocketEnableCallBacks(_socket, kCFSocketAcceptCallBack);
CFRunLoopRef cfRunLoop = CFRunLoopGetCurrent ();
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource (kCFAllocatorDefault, _socket, 0);
CFRunLoopAddSource (cfRunLoop, source, kCFRunLoopCommonModes);
return 1;
}
void TCPServerAcceptCallBack (CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void * data, void * info) {
if (kCFSocketAcceptCallBack == type) {
// Local socket handle
CFSocketNativeHandle nativeSocketHandle = * (CFSocketNativeHandle *) data;
uint8_t name [SOCK_MAXADDRLEN];
socklen_t nameLen = sizeof (name);
if (0 != getpeername (nativeSocketHandle, (struct sockaddr *) name, & nameLen)) {
NSLog (#"error");
// Exit (1);
}
NSLog (# "%s connected.", inet_ntoa (((struct sockaddr_in *) name) -> sin_addr));
CFReadStreamRef iStream;
CFWriteStreamRef oStream;
CFReadStreamClientCallBack readStream;
CFReadStreamClientCallBack writeStream;
CFWriteStreamRef wStream;
// Create a socket connection can read and write
CFStreamCreatePairWithSocket (kCFAllocatorDefault, nativeSocketHandle, &iStream, & oStream);
if (iStream && oStream) {
CFStreamClientContext streamContext = {0, NULL, NULL, NULL};
if (! CFReadStreamSetClient (iStream, kCFStreamEventHasBytesAvailable,
readStream, // callback function is called when the data readable
&streamContext)) {
// Exit (1);
}
if (! CFReadStreamSetClient (iStream, kCFStreamEventCanAcceptBytes, writeStream, &streamContext)) {
// Exit (1);
}
CFReadStreamScheduleWithRunLoop (iStream, CFRunLoopGetCurrent (), kCFRunLoopCommonModes);
CFWriteStreamScheduleWithRunLoop (wStream, CFRunLoopGetCurrent (), kCFRunLoopCommonModes);
CFReadStreamOpen (iStream);
CFWriteStreamOpen (wStream);
}
else
{
close (nativeSocketHandle);
}
}
}
// Read data
void readStream (CFReadStreamRef stream, CFStreamEventType eventType, void * clientCallBackInfo) {
UInt8 buff [255];
CFReadStreamRead (stream, buff, 255);
printf ("received:%s", buff);
}
void writeStream (CFWriteStreamRef stream, CFStreamEventType eventType, void * clientCallBackInfo) {
outputStream = stream;
}
//int main()
//{
// char * str = "nihao";
// UInt8 buff [255];
// if (outputStream != NULL) {
// CFWriteStreamWrite (outputStream, buff, strlen (str) + 1);
// }
// else
// {
// NSLog (# "Cannot send data!");
// }
//}
// Open up a thread in the thread function
void runLoopInThread () {
int res = setupSocket ();
if (res) {
EXIT_FAILURE;
}
CFRunLoopRun (); // run the current thread CFRunLoop of objects
}
In the above code crashes for Server when CFSocketConnectToAddress executes in Client and after that client app also crashes.
Dealing with a CFSockets will get you in the world of dealing with POSIX foundations and stuff. If your looking for a simple echo/chat server, you should firstly go to NSStream. It's way easier. Here's an example:
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)HOST, PORT, &readStream, &writeStream);
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (NSOutputStream *)CFBridgingRelease(writeStream);
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
And handling the input be like:
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(#"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
if (theStream == inputStream) {
uint8_t buffer[100240];
NSInteger len;
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if (nil != output) {
NSLog(#"Server Response: %#", output);
[self stream:theStream didRecieveResponse:output];
}
}
}
}
break;
case NSStreamEventErrorOccurred:
[self requestDidFailWithResults:#"Can not connect to the host!" andError:theStream.streamError];
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
theStream = nil;
break;
case NSStreamEventEndEncountered:
[self requestDidFailWithResults:#"Request ended" andError:theStream.streamError];
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
theStream = nil;
break;
case NSStreamEventHasSpaceAvailable:
NSLog(#"OutStream is ready");
break;
default:
[self requestDidFailWithResults:#"Unknown event" andError:theStream.streamError];
}
}
_socket = CFSocketCreate (kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)kCFSocketAcceptCallBack, NULL);
In above method i had to pass my callback method instead of "(CFSocketCallBack)kCFSocketAcceptCallBack".Which fixed my issue.
Related
The input stream works fine if data is sent after a short delay on server. The issue is occurring only when the server makes a response immediately after receiving data. I am handling both input and output streams in the same class.
Creating Streams:
// STREAMS
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
// CREATE READABLE/WRITABLE STREAMS TO HOST/PORT
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)terminalIp, [terminalPort intValue], &readStream, &writeStream);
// SET STREAMS
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;
// SETTING DELEGATES
[inputStream setDelegate:self];
[outputStream setDelegate:self];
// SET LOOP TO LISTEN FOR MESSAGES
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
// OPEN STREAMS
[inputStream open];
[outputStream open];
Stream Delegate Event Handler:
////////////////////////////////////
// FUNCTION - STREAM EVENT HANDLER
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
// LOG
if(aStream == outputStream){
NSLog(#"Status of outputStream: %lu", (unsigned long)[outputStream streamStatus]);
}else{
NSLog(#"Status of inputStream: %lu", (unsigned long)[inputStream streamStatus]);
}
//
// CHECK EVENTS
//
if(eventCode == NSStreamEventOpenCompleted){
//
// STREAM OPEN
//
}else if(eventCode == NSStreamEventHasBytesAvailable){
//
// SERVER SENT BYTES
//
// CHECK STREAM TYPE
if(aStream == inputStream){
// SETTINGS
uint8_t buffer[1024];
// LOOP WHILE THERE ARE BYTES BEING RECIVED
while ([inputStream hasBytesAvailable]){
// MAKE SURE THERE ARE BYTES
if([inputStream read:buffer maxLength:sizeof(buffer)] > 0){
// SET HEX RESPONSE
hexResponse = [[NSData alloc] initWithBytes:buffer length:[inputStream read:buffer maxLength:sizeof(buffer)]];
NSLog(#"hex in stream: %#",hexResponse);
NSString *incomingString;
if (hexResponse.length >= 2){
// TURN HEX INTO STRING
incomingString = [[NSString alloc] initWithData:hexResponse encoding:NSUTF8StringEncoding];
NSLog(#"%#", incomingString);
}
// MAKE SURE THERE IS TEXT THERE
if(incomingString.length > 3){
// SET TEXT
stringResponse = incomingString;
}
}
}
}
}else if(eventCode == NSStreamEventErrorOccurred){
//
// COULDN'T CONNECT
//
NSError *theError = [aStream streamError];
NSLog(#"Stream Error (%ld): %#",(long)[theError code],[theError localizedDescription]);
}else if(eventCode == NSStreamEventEndEncountered){
//
// END
//
// CHECK STREAM TYPE
if(aStream == outputStream){
NSData *newData = [outputStream propertyForKey:
NSStreamDataWrittenToMemoryStreamKey];
if (!newData) {
NSLog(#"No data written to memory from output stream!");
} else {
//[self processData:newData];
// CONVERT
//[self translateResponse];
}
[outputStream close];
[outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
outputStream = nil;
}else if(aStream == inputStream){
NSData *newData = [inputStream propertyForKey:
NSStreamDataWrittenToMemoryStreamKey];
if (!newData) {
NSLog(#"No data written to memory from input stream!");
} else {
NSLog(#"Data found in input stream!");
//[self processData:newData];
// CONVERT
[self translateResponse];
}
[inputStream close];
[inputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
inputStream = nil;
}
}else if(eventCode == NSStreamEventHasSpaceAvailable){
//
// HAS SPACE TO SEND
//
if(aStream == outputStream){
NSMutableData * dataToSend = [NSMutableData dataWithData:hexRequest];
uint8_t *readBytes = (uint8_t *)[dataToSend mutableBytes];
readBytes += byteIndex; // instance variable to move pointer
NSUInteger data_len = [dataToSend length];
unsigned long len = ((data_len - byteIndex >= 1024) ?
1024 : (data_len-byteIndex));
uint8_t buf[len];
(void)memcpy(buf, readBytes, len);
len = [outputStream write:(const uint8_t *)buf maxLength:len];
byteIndex += len;
}
}else{
//
// UNKNOWN EVENT
//
}
} // END FUNCTION
The problem was caused by reading the input buffer twice. I was reading it in a conditional statement as well as when I assigned it. The problem was fixed by assigning it first.
New Code:
}else if(eventCode == NSStreamEventHasBytesAvailable){
//
// SERVER SENT BYTES
//
// CHECK STREAM
if(aStream == inputStream){
// SSET BUFFER
uint8_t buffer[1024];
// LOOP WHILE THERE ARE BYTES BEING RECIVED
while ([(NSInputStream *)aStream hasBytesAvailable]){
// READ BUFFER
hexResponse = [[NSData alloc] initWithBytes:buffer length:[(NSInputStream *)aStream read:buffer maxLength:sizeof(buffer)]];
// MAKE SURE THERE IS DATA
if([hexResponse length] > 0){
// INIT INCOMING STRING
NSString *incomingString;
// MAKE SURE RESPONSE IS NOT A HEARTBEAT
if (hexResponse.length >= 2){
// TURN HEX INTO STRING
incomingString = [[NSString alloc] initWithData:hexResponse encoding:NSUTF8StringEncoding];
NSLog(#"%#", incomingString);
}
// MAKE SURE INCOMING STRING IS VALID
if(incomingString.length > 3){
// SET TEXT
stringResponse = incomingString;
}
}
}
}
}
So, I wanted to learn how to write data back and forth over a tcp socket in objective-c and I can't seem to get it to connect to my server. I verified that my server is operating properly by writing the c code to connect with the server and it works. I just can't get the connection to happen in objective-c.
Here is the code-
- (void)searchForSite
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"URL", PORT, &readStream, &writeStream);
if(!CFWriteStreamOpen(writeStream)) {
NSLog(#"Error, writeStream not open");
return;
}
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
inStream = inputStream;
outStream = outputStream;
[inputStream open];
[outputStream open];
CFWriteStreamWrite(writeStream, "Hello\n", 6);
}
This c code works and gives me a connection on the server side:
void con(NSString *x)
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
char *node = "URL";
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(node, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
}
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("client: socket");
continue; }
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
continue;
}
break; }
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1); }
buf[numbytes] = '\0';
printf("client: received '%s'\n",buf);
close(sockfd);
}
URL is an ipv4 address.
Any suggestions?
I want to create a TCP server on the iPhone. I tried to write this server using Apple's developer help, but I had no success.
I tried to listen with CoreFoundation and with POSIX Socket API but none of these worked.
Using CoreFoundation I implemented the following:
CFSocketRef myipv4cfsock = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP,
kCFSocketAcceptCallBack, handleConnect, NULL);
struct sockaddr_in mySocket;
memset(&mySocket, 0, sizeof(sin));
mySocket.sin_len = sizeof(sin);
mySocket.sin_family = PF_INET;
mySocket.sin_port = 8000;
mySocket.sin_addr.s_addr= INADDR_ANY;
CFSocketSetAddress(myipv4cfsock, CFDataCreate(kCFAllocatorDefault, (UInt8 *)&mySocket, sizeof(mySocket)));
CFRunLoopSourceRef socketsource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, myipv4cfsock, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), socketsource, kCFRunLoopDefaultMode);
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStringRef remoteHost = CFSTR("localhost");
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)remoteHost, 8000, &readStream, &writeStream);
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream setDelegate: self];
[outputStream setDelegate: self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
Using the POSIX Socket API I implemented this:
int listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in socketAddr;
memset(&socketAddr, 0, sizeof(socketAddr));
socketAddr.sin_len = sizeof(sin);
socketAddr.sin_family = AF_INET;
socketAddr.sin_port = 8000;
socketAddr.sin_addr.s_addr= INADDR_ANY;
if (bind(listenSocket, (struct sockaddr *)&socketAddr, sizeof(socketAddr)) < 0)
{
NSLog(#"Error: Could not bind socket.");
}
listen(listenSocket, 10);
But then I didn't know how to handle the events with Grand Central Dispatch.
When I try to connect with some client I always get the exception "Connection refused" on client side.
Does anybody have some example code?
I found a solution using the POSIX Socket API.
int listenfd = 0;
struct sockaddr_in serv_addr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(8008);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
_listenForConnections = true;
listen(listenfd, 10);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(#"Waiting for connections...");
while (_listenForConnections)
{
__block int connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
NSLog(#"Connection accepted");
char buffer[1024];
bzero(buffer, 1024);
NSString *message = #"";
bool continueReading = true;
do
{
recv(connfd , buffer , 1024 , 0);
int size = strlen(buffer);
if ((buffer[size-1] == '}' && buffer[size-2] == '{'))
{
continueReading = false;
buffer[size-2] = '\0';
}
message = [NSString stringWithFormat: #"%#%s", message, buffer];
}while (continueReading);
NSLog(#"Got message from client");
char* answer = "Hello World";
write(connfd, answer, strlen(answer));
}
NSLog(#"Stop listening.");
close(listenfd);
});
I am new to socket programming.I am trying to track bytes sent and received through all sockets opened in my iPhone. Which data structure present in iOS, gives information about these? I tried below code posted in one of the SO question, but it is giving data from last reboot time. I want to list all sockets established in my iPhone and track bytes sent and received through each socket
- (NSArray *)getDataCounters {
BOOL success;
struct ifaddrs *addrs;
const struct ifaddrs *cursor;
const struct if_data *networkStatisc;
int WiFiSent = 0;
int WiFiReceived = 0;
int WWANSent = 0;
int WWANReceived = 0;
NSString *name=[[[NSString alloc]init]autorelease];
success = getifaddrs(&addrs) == 0;
if (success)
{
cursor = addrs;
while (cursor != NULL)
{
name=[NSString stringWithFormat:#"%s",cursor->ifa_name];
NSLog(#"ifa_name %s == %#\n", cursor->ifa_name,name);
// names of interfaces: en0 is WiFi ,pdp_ip0 is WWAN
if (cursor->ifa_addr->sa_family == AF_LINK)
{
if ([name hasPrefix:#"en"])
{
networkStatisc = (const struct if_data *) cursor->ifa_data;
WiFiSent+=networkStatisc->ifi_obytes;
WiFiReceived+=networkStatisc->ifi_ibytes;
NSLog(#"WiFiSent %d ==%d",WiFiSent,networkStatisc->ifi_obytes);
NSLog(#"WiFiReceived %d ==%d",WiFiReceived,networkStatisc->ifi_ibytes);
}
if ([name hasPrefix:#"pdp_ip"])
{
networkStatisc = (const struct if_data *) cursor->ifa_data;
WWANSent+=networkStatisc->ifi_obytes;
WWANReceived+=networkStatisc->ifi_ibytes;
NSLog(#"WWANSent %d ==%d",WWANSent,networkStatisc->ifi_obytes);
NSLog(#"WWANReceived %d ==%d",WWANReceived,networkStatisc->ifi_ibytes);
}
}
cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
return [NSArray arrayWithObjects:[NSNumber numberWithInt:WiFiSent], [NSNumber numberWithInt:WiFiReceived],[NSNumber numberWithInt:WWANSent],[NSNumber numberWithInt:WWANReceived], nil];
I think you should go from basics.
This is how we open socket for input and outputsream.
- (IBAction)searchForSite:(id)sender
{
NSString *urlStr = [sender stringValue];
if (![urlStr isEqualToString:#""]) {
NSURL *website = [NSURL URLWithString:urlStr];
if (!website) {
NSLog(#"%# is not a valid URL");
return;
}
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 80, &readStream, &writeStream);
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
/* Store a reference to the input and output streams so that
they don't go away.... */
...
}
}
this is the delegate method,whick will called every time when you will read or write to socket.
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(#"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
break;
case NSStreamEventHasSpaceAvailable
break;
case NSStreamEventErrorOccurred:
NSLog(#"Can not connect to the host!");
break;
case NSStreamEventEndEncountered:
break;
default:
NSLog(#"Unknown event");
}
}
for more information refer links.
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Streams/Articles/NetworkStreams.html#//apple_ref/doc/uid/20002277-BCIDFCDI
http://www.raywenderlich.com/3932/networking-tutorial-for-ios-how-to-create-a-socket-based-iphone-app-and-server
Im writing an IOS application for my first time. It is supposed to connect to a static IP device, and send certain "known" commands to it. But for some reason Im unable to establish a connection.
Bellow are the functions I use to establish my connection, and write data to the port.
-(void)connection//:(NSString *)serviceName forIpAddress:(NSString *)ipAddress forPort:(NSString *)portNo
{
if(input && output)
[self close];
NSString *urlString = [NSString stringWithFormat:#"%.%.%.%", "192.168.3.120"];
NSURL *website = [NSURL URLWithString:urlString];
if (!website) {
NSLog(#"%# is not a valid URL", website);
}
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)[website host], 43, &readStream, &writeStream);
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
NSInputStream *input = (__bridge NSInputStream *)readStream;
NSOutputStream *output= (__bridge NSOutputStream *)writeStream;
}
- (void)open {
[input setDelegate:self];
[output setDelegate:self];
[input scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[output scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode]; [input open];
[output open];
}
-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
NSString *event;
switch (streamEvent)
{
case NSStreamEventNone:
event = #"NSStreamEventNone";
break;
case NSStreamEventOpenCompleted:
event = #"NSStreamEventOpenCompleted";
break;
case NSStreamEventHasBytesAvailable:
event = #"NSStreamEventHasBytesAvailable";
if (theStream == input)
{
uint8_t buffer[1024];
NSInteger len;
while ([input hasBytesAvailable])
{
len = [input read:buffer maxLength:1024];
if (len > 0)
{
NSMutableString *output = [[NSMutableString alloc]initWithBytes:buffer length:len encoding:NSUTF8StringEncoding]; NSLog(#"Received data--------------------%#", output);
}
}
}
break;
case NSStreamEventHasSpaceAvailable:
event = #"NSStreamEventHasSpaceAvailable";
break;
case NSStreamEventErrorOccurred:
event = #"NSStreamEventErrorOccurred";
//[self close];
break;
case NSStreamEventEndEncountered:
break; default:
event = #"NSStreamEventEndEncountered";
//[self close];
event = #"Unknown"; break;
}
NSLog(#"event------%#",event);
}
- (void)close
{
[input close];
[output close];
[input removeFromRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];
[output removeFromRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];
[input setDelegate:nil];
[output setDelegate:nil];
input = nil;
output = nil;
}
- (void)dataSending:(NSString*)data
{
if(output)
{
if(![output hasSpaceAvailable])
return;
NSData *_data=[data dataUsingEncoding:NSUTF8StringEncoding];
NSInteger data_len = [_data length];
uint8_t *readBytes = (uint8_t *)[_data bytes];
int byteIndex=0;
unsigned int len=0;
while (TRUE)
{
len = ((data_len - byteIndex >= 40960) ? 40960 : (data_len-byteIndex));
if(len==0)
break;
uint8_t buf[len];
(void)memcpy(buf, readBytes, len);
len = [output write:(const uint8_t *)buf maxLength:len];
byteIndex += len;
readBytes += len;
}
NSLog(#"Sent data----------------------%#",data);
}
}
I do call the mentioned functions through that code as a test, and nothing happens
- (IBAction)pumpchange:(id)sender {
[self connection];
[self open];
if ([self.pump backgroundImageForState:(UIControlStateNormal)]==[UIImage imageNamed:#"PumpOff.png"])
{
[self.pump setBackgroundImage:[UIImage imageNamed:#"PumpOn.png"] forState:(UIControlStateNormal)];
[self dataSending:#"pump_on"];
}
else //if ([self.pump backgroundImageForState:(UIControlStateNormal)]==[UIImage imageNamed:#"PumpOn.png"])
{
[self.pump setBackgroundImage:[UIImage imageNamed:#"PumpOff.png"] forState:(UIControlStateNormal)];
[self dataSending:#"pump_off"];
}
[self close];
}
Thanks in Advance
There seem to be some misunderstandings how format strings work, because
NSString *urlString = [NSString stringWithFormat:#"%.%.%.%", "192.168.3.120"];
just gives you the string #"...". Perhaps you meant
NSString *urlString = [NSString stringWithFormat:#"%d.%d.%d.%d", 192, 168, 3, 120];
or
NSString *urlString = [NSString stringWithFormat:#"%s", "192.168.3.120"];
But you don't need a format string at all:
NSString *urlString = #"192.168.3.120";