//---------------------------------------------------------------------------------------
// EDTCPSocket.m created by erik
// @(#)$Id: EDTCPSocket.m,v 2.0 2002/08/16 18:12:48 erik Exp $
//
// Copyright (c) 1997-2001 by Erik Doernenburg. All rights reserved.
//
// Permission to use, copy, modify and distribute this software and its documentation
// is hereby granted, provided that both the copyright notice and this permission
// notice appear in all copies of the software, derivative works or modified versions,
// and any portions thereof, and that both notices appear in supporting documentation,
// and that credit is given to Erik Doernenburg in all documents and publicity
// pertaining to direct or indirect use of this code or its derivatives.
//
// THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE
// SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS
// "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY
// DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE
// OR OF ANY DERIVATIVE WORK.
//---------------------------------------------------------------------------------------
#import <Foundation/Foundation.h>
#import "osdep.h"
#import "EDTCPSocket.h"
#ifdef WIN32
#define EDSOCKETHANDLE ((int)[self nativeHandle])
#else
#define EDSOCKETHANDLE [self fileDescriptor]
#endif
//---------------------------------------------------------------------------------------
@implementation EDTCPSocket
//---------------------------------------------------------------------------------------
/*" This class implementes TCP sockets and some methods specific to such sockets. Most of the commonly used functionality is in its superclasses #EDIPSocket and #NSFileHandle as well as in the NSFileHandle category defined in this framework.
The following code example shows how to set up a client socket, and connect it to Apple's web server: !{
EDTCPSocket *socket;
socket = [EDTCPSocket socket];
[socket connectToHost:[NSHost hostWithName:hostname] port:80]
}
The following code example shows how to set up a server socket, listening on the standard web port on all interfaces of this host. If we are debugging it sets the "re-use address" option so that we don't have to wait to set up the socket after restarting our application: !{
EDTCPSocket *socket;
socket = [EDTCPSocket socket];
\#if DEBUG
[socket setAllowsAddressReuse:YES];
\#endif
[socket startListeningOnLocalPort:80];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(newClientNotification:)
name:NSFileHandleConnectionAcceptedNotification
object:socket];
[socket acceptConnectionInBackgroundAndNotify];
}
Note that, generally, working with #EDStreams is a better choice than working directly with sockets.
"*/
//---------------------------------------------------------------------------------------
// CLASS ATTRIBUTES
//---------------------------------------------------------------------------------------
+ (int)socketProtocol
{
return IPPROTO_TCP;
}
+ (int)socketType
{
return SOCK_STREAM;
}
//---------------------------------------------------------------------------------------
// OPTIONS & PARAMETERS
//---------------------------------------------------------------------------------------
/*" Controls wether data written to the socket is sent immediatly or whether the operating system should try to accumulate some data before sending a packet to reduce overhead. This is commonly known as Nagle's algorithm (RFC 896) and corresponds to TCP_NODELAY. "*/
- (void)setSendsDataImmediately:(BOOL)flag
{
[self setSocketOption:TCP_NODELAY level:IPPROTO_TCP value:flag];
}
//---------------------------------------------------------------------------------------
// LISTENING
//---------------------------------------------------------------------------------------
/*" Starts listening for incoming connections. This requires that a local port has been set before. Note that #acceptConnectionInBackgroundAndNotify must be called afterwards so that incoming connections are handled. "*/
- (void)startListening
{
if(listen(EDSOCKETHANDLE, 5) == -1) // backlog length of 5 is maximum
[NSException raise:NSFileHandleOperationException format:@"Unable start listening on local port: %s", strerror(ED_ERRNO)];
flags.listening = YES;
}
/*" Starts listening for incoming connections on aPort on all local IP addresses (interfaces). Note that #acceptConnectionInBackgroundAndNotify must be called afterwards so that incoming connections are handled. "*/
- (void)startListeningOnLocalPort:(unsigned short)aPort
{
[self setLocalPort:aPort];
[self startListening];
}
/*" Starts listening for incoming connections on the aPort on the specified local address; the latter being in the "typical" dotted numerical notation. Note that #acceptConnectionInBackgroundAndNotify must be called afterwards so that incoming connections are handled. "*/
- (void)startListeningOnLocalPort:(unsigned short)aPort andAddress:(NSString *)addressString
{
[self setLocalPort:aPort andAddress:addressString];
[self startListening];
}
//---------------------------------------------------------------------------------------
@end
//---------------------------------------------------------------------------------------