PBSocket.m


max21 Unternehmensgruppe
//
// PBSocket.m
//
// derived from SmallSockets Library (http://smallsockets.sourceforge.net/)
//
// Copyright (C) 2001 Steven Frank (stevenf@panic.com)
//
// This software is provided 'as-is', without any express or implied 
// warranty. In no event will the authors be held liable for any damages 
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose, 
// including commercial applications, and to alter it and redistribute it 
// freely, subject to the following restrictions:
//
//     1. The origin of this software must not be misrepresented; you must 
//        not claim that you wrote the original software. If you use this 
//        software in a product, an acknowledgment in the product 
//        documentation (and/or about box) would be appreciated but is not 
//        required.
//
//     2. Altered source versions must be plainly marked as such, and must
//        not be misrepresented as being the original software.
//
//     3. This notice may not be removed or altered from any source 
//        distribution.
//        
// modified by Pirmin Braun pirmin@pirmin.de
 
#import "PBSocket.h"
/* Windows-System */
#ifndef GNUSTEP
#include <winsock.h>
#include <io.h>
/* Unix-System */
#else
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif
@implementation PBSocket
ACCESSm(remoteHostName,setRemoteHostName)
- (id)init
//
// Designated initializer
//
{    
    if(!(self=[super init]))return nil;
    connected = NO;
    listening = NO;
    [self setRemoteHostName:nil];
    remotePort = SOCKET_INVALID_PORT;
    // Create socket
    if ( (socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )return nil;
    return self;
}
+ (PBSocket *)socket
//
// Creates a Socket and returns it.
// The new Socket will be autoreleased, so be sure to retain it if you
// need to keep it around.
//
// Note: Sockets are blocking by default.
//
{
    return [[[PBSocket alloc] init] autorelease];
}
- (void)dealloc
//
// Do not call this method directly!  Use retain & release.
//
{
    [self close];
    [remoteHostName release];
    [super dealloc];
}
- (void)close
//
// Closes the socket.  You generally do not need to call this, as the socket
// will be automatically closed when it is released.
//
{
    if ( socketfd != SOCKET_INVALID_DESCRIPTOR )
    {
        close(socketfd);
        socketfd = SOCKET_INVALID_DESCRIPTOR;
    }
    [self setRemoteHostName:nil];
    connected = NO;
    listening = NO;
    remotePort = SOCKET_INVALID_PORT;
}
- (void)connectToHostName:(NSString*)hostName port:(unsigned short)port
//
// Connect the socket to the host specified by hostName, on the requested port.
//
{
    struct hostent* remoteHost;
    struct sockaddr_in remoteAddr;
    // Socket must be created, and not already connected
    if ( socketfd == SOCKET_INVALID_DESCRIPTOR )
        [NSException raise:SOCKET_EX_BAD_SOCKET_DESCRIPTOR 
                        format:SOCKET_EX_BAD_SOCKET_DESCRIPTOR];
    
    if ( connected )
        [NSException raise:SOCKET_EX_ALREADY_CONNECTED 
                        format:SOCKET_EX_ALREADY_CONNECTED];
    
    // Look up host 
    
    if ( (remoteHost = gethostbyname([hostName cString])) == NULL )
        [NSException raise:SOCKET_EX_HOST_NOT_FOUND 
                        format:SOCKET_EX_HOST_NOT_FOUND_F, strerror(errno)];
    
    // Copy host address and port into socket address structure
    
    memset((char*)&remoteAddr, 0, sizeof(remoteAddr));
    remoteAddr.sin_family = AF_INET;
    memcpy((char*)&remoteAddr.sin_addr.s_addr, (char*)remoteHost->h_addr, remoteHost->h_length);
    remoteAddr.sin_port = htons(port);
    // Request connection, raise on failure
    
    if ( (connect(socketfd, (struct sockaddr*)&remoteAddr, sizeof(remoteAddr)) < 0) )
        [NSException raise:SOCKET_EX_CONNECT_FAILED 
                        format:SOCKET_EX_CONNECT_FAILED_F, strerror(errno)];
    // Note successful connection
    [self setRemoteHostName:hostName];
    remotePort = port;
    connected = YES;
}
- (BOOL)connected;
{
    return connected;
}
- (void)readData:(NSMutableData *)data;
//
// Append any available data from the socket to the supplied buffer.
// Returns number of bytes received.  (May be 0)
//
{
    int count = 0;
    
    // data must not be null ptr
    if (!data)return;
    // Socket must be created and connected
    if ( socketfd == SOCKET_INVALID_DESCRIPTOR )return;
    if ( !connected )return;
    
    // Request a read of as much as we can.  Should return immediately if no data.
    NS_DURING;
    while((count = recv(socketfd, readBuffer, SOCKET_DEFAULT_READ_BUFFER_SIZE, 0))>0){
        [data appendBytes:readBuffer length:count];
    }
    NS_HANDLER;
    NS_ENDHANDLER;
    [self close];
}
- (void)writeData:(NSData*)data
//
// Writes the given data to the socket
//
{
    const char* bytes = [data bytes];    
    int len = [data length];
    int sent;
    
    // Socket must be created and connected
    
    if ( socketfd == SOCKET_INVALID_DESCRIPTOR )
        [NSException raise:SOCKET_EX_BAD_SOCKET_DESCRIPTOR 
                        format:SOCKET_EX_BAD_SOCKET_DESCRIPTOR];
    if ( !connected )
        [NSException raise:SOCKET_EX_NOT_CONNECTED 
                        format:SOCKET_EX_NOT_CONNECTED];
    
    // Send the data
    
    while ( len > 0 )
    {
        sent = send(socketfd, bytes, len, 0);
        
        if ( sent < 0 )
            [NSException raise:SOCKET_EX_SEND_FAILED 
                            format:SOCKET_EX_SEND_FAILED_F, strerror(errno)];    
        
        bytes += sent;
        len -= sent;
    }
}
- (void)writeString:(NSString*)string
//
// Writes the given string to the socket
//
{
    if ( [string length] > 0 ) 
        [self writeData:[string dataUsingEncoding:NSUTF8StringEncoding]]; 
}
@end
Foto