Can't seem to get this iOS tcp socket to work - ios

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?

Related

Input stream calling event NSStreamEventHasBytesAvailable, but the stream contains no bytes

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;
}
}
}
}
}

How to create a TCP Server on the iPhone?

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);
});

CFSocket crashes on successful connection

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.

NSStream not giving any data

I'm trying to write telnet client on iOS and I can't set up streams correctly. I think that they work, but I am getting empty buffer each time I get delegate method triggered.
Here is how I set up streams:
self.manager = [[TelnetManager alloc] init];
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)[[NSURL URLWithString:#"arda.pp.ru"] host], 7000, &readStream, &writeStream);
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream setDelegate:self.manager];
[outputStream setDelegate:self.manager];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
Here is the delegate method that is on manager that handles events:
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
if (eventCode == NSStreamEventHasBytesAvailable) {
NSLog(#"We got some data over here");
if(!_data) {
_data = [NSMutableData data];
}
uint8_t buf[1024];
unsigned int len = 0;
len = [(NSInputStream *)aStream read:buf maxLength:1024];
NSLog(#"length - %d", len);
NSLog(#"buf:%s", buf);
if(len) {
[_data appendBytes:(const void *)buf length:len];
_bytesRead = #([_bytesRead intValue]+len);
} else {
NSLog(#"no buffer!");
}
}
}
It is getting fired, but buffer is always empty and "no buffer" is logged.
What's wrong with my code?
There actually is nothing wrong with your code. I have used it to connect to a telnet server and it worked fine.
In your code, "no buffer" is logged when len is 0, which means the buffer's end has been reached. In the case of a telnet server, this usually means that either the server disconnected your connection or the server quit.

iOS socket programming - receiving nsstream event 4

I am using a device called a WiFly that has ip address:169.254.1.1 and port 2000. I am trying to connect to this device via an iOS application. I use the following code to connect:
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
UInt32 port = 2000;
CFStringRef host = CFSTR("169.254.1.1");
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, &readStream, &writeStream);
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;
// set the delegates to this view controller
[inputStream setDelegate:self];
[outputStream setDelegate:self];
// Set run loops to continuous receive information
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
// Finally, open the connection
[inputStream open];
[outputStream open];
Then I use the following to handle stream events:
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
NSLog(#"stream event %i", streamEvent);
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(#"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
if (theStream == inputStream) {
uint8_t buffer[1024];
int 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 said: %#", output);
[self messageReceived:output];
}
}
}
}
break;
case NSStreamEventErrorOccurred:
NSLog(#"Can't connect to server");
break;
case NSStreamEventEndEncountered:
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
break;
default:
NSLog(#"Unknown event");
}
So, I can see that the first two streams are opened correctly. Then it follows immediately with a stream event 4, which from my understanding is to be expected. However, I then try to call a function:
- (IBAction)moveForward
{
NSLog(#"move forward called");
NSString *response = [NSString stringWithFormat:#"2"];
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
}
Which should return "forward" from an arduino uno via the wifly. However, when I click, I get another NSStreamEvent 4 for some reason. I also telnetted in to the device via the terminal with:
telnet 169.254.1.1 2000
and subsequently type a "2"... This returned the desired "forward" immediately. What am I doing wrong from the perspective of the iPad?
Help is much appreciated!
EDIT For some reason, everytime the handler is accessed, the stream that is passed is the output stream, which is completely wrong... Why wouldn't the input stream ever be passed through?
And here is the arduino code:
void loop()
{ while (Serial.available() > 0) {
int next = Serial.parseInt();if(Serial.available() > 0)
{
if(next == 20) {
Serial.println("leftMove");
}}}}

Resources