0

我正在开发 Objective-C 中的客户端/服务器软件包,并且在运行时收到“无法识别的选择器发送到实例”错误。我是 Objective-C 的新手,所以我想在这里得到一些帮助。

以下是两个可能有用的代码文件:

GuiController.m

    #import "GuiController.h"
    #import "AppDelegate.h"
    #import "ClientSocket.h"
    #import "UploaderThread.h"
    #import "DownloaderThread.h"


    // to see debug messages, change NO below to YES
    #define DEBUGON YES
    // buffer size for reading byte arrays to/from server
    #define MAXDATASIZE 1024
    /**
     * Foundations of Distributed Applications
     * see http://pooh.poly.asu.edu/Cst420
     * @author Christopher Sosa (smoothpinkjazz@gmail.com), ASU Polytechnic, Software Engineering
     * @version December 2012
     */

    @implementation GuiController

    - (id) initWithDelegate: (AppDelegate*) theDelegate
                   host: (NSString*) hostName
                   port: (NSString*) portNum {
    // set self to result of initializing parent. If initialization succeeds
        if ( (self = [super init])) {
    // set properties and increment the reference count for its object.
    appDelegate = [theDelegate retain];
    albTB = [appDelegate albumTB];
    [albTB setStringValue:[NSString stringWithFormat:@"Probably should look for server %s:%s",[hostName UTF8String],[portNum UTF8String]]];
    titCB = [appDelegate titleCB];
    [titCB setDelegate:self];
    authTB = [appDelegate authorTB];
    [authTB setDelegate:self];
    host = hostName;
    port = portNum;
    int songSockPortInt = [port intValue] + 100;
    NSString *songSockPort = [NSString stringWithFormat:@"%d", songSockPort];
    char *buf = malloc(MAXDATASIZE);
    NSString *identStr;
    if (buf) {
      mainSock = [[ClientSocket alloc] initWithHost:hostName portNumber:portNum];
      [mainSock connect];
      identStr = [mainSock recieveBytes:buf maxBytes:MAXDATASIZE beginAt:0];
      ident = [identStr intValue];
      songSock = [[ClientSocket alloc] initWithHost:host portNumber:songSockPort];
      [songSock connect];
    }
    [identStr release];
    free(buf);
        }
        return self;
    }

    - (void) dealloc {
        [appDelegate release];
        [albTB release];
        [titCB release];
        [authTB release];
        [mainSock release];
        [songSock release];
        [super dealloc];
    }

    - (void) saveLib {
        [self debug:[NSString stringWithFormat:@"asked to save.\n"]];
        NSString * saveStr = @"save";
        char * buf = malloc(MAXDATASIZE);
        if (buf) {
            int sent = [mainSock sendBytes:[saveStr UTF8String] OfLength:[saveStr length]
            Index:0];
            NSString* retStr = [mainSock receiveBytes: buf maxBytes:MAXDATASIZE beginAt:0];
            [[appDelegate albumTB] setStringValue:
            [NSString stringWithFormat:@"Save result: %s",[retStr UTF8String]]];
            free(buf);
            [self debug:[NSString stringWithFormat:@"save return: %s\n",
            [retStr UTF8String]]];
        }
        [[appDelegate albumTB] setStringValue: [NSString stringWithFormat:@"Saved"]];
    }

    - (void) restoreLib {
        NSString * restoreStr = @"restore";
        [self debug:[NSString stringWithFormat:@"asked to restore.\n"]];
        char * buf = malloc(MAXDATASIZE);
        if (buf) {
            int sent = [mainSock sendBytes:[restoreStr UTF8String] OfLength:[restoreStr length] Index:0];
            NSString* retStr = [mainSock receiveBytes: buf maxBytes:MAXDATASIZE beginAt:0];
            [[appDelegate albumTB] setStringValue:
            [NSString stringWithFormat:@"Restore result: %s",[retStr UTF8String]]];
            free(buf);
            [self debug:[NSString stringWithFormat:@"restore return: %s\n",
            [retStr UTF8String]]];
        }
       [[appDelegate albumTB] setStringValue:[NSString stringWithFormat:@"Restored"]];
    }

    - (void) addMD {
        NSString * addMusicStr = @"add";
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        ClientSocket *addSock;
        UploaderThread * uploader;
        @try {  
            [self debug:[NSString stringWithFormat:@"openWav called:\n"]];
            NSOpenPanel *panel;
            NSString *path;

            panel = [NSOpenPanel openPanel];
            [panel setAllowsMultipleSelection: NO];
            [panel runModalForTypes: [NSSound soundUnfilteredFileTypes]];

            path = [[panel filenames] objectAtIndex: 0];

            if (sound != nil) {
                [sound stop];
                [sound release];
            }
            sound = [[NSSound alloc] initWithContentsOfFile: path byReference: NO];
            if (!sound) {
                NSRunAlertPanel (@"Error", @"Could not open selected file", @"OK", nil, nil);
                return;
            }
            NSString * song = [NSString stringWithFormat:@"%@@%@@%@ ", [authTB stringValue], [titCB stringValue], [albTB stringValue]];

            addSock = [[ClientSocket alloc] initWithHost:host portNumber:@"9001"];
            [addSock connect];
            int sent = [mainSock sendBytes:[addMusicStr UTF8String] OfLength:[addMusicStr length] Index:0];
            int sentSong = [mainSock sendBytes:[song UTF8String] OfLength:[song length] Index:0];
            uploader = [[UploaderThread alloc] initWithName:path client:self socket:addSock];
            [(NSThread*)uploader start];
        } @catch (NSException *e) {
            [self debug:[NSString stringWithFormat:@"%@ Exception (%@)", [e name], [e reason]]];
        } 
        [uploader release];
        [addSock release];
        [sound setDelegate: self];
        [pool release];
        [self refreshMD];
    }

    - (void) removeMD {
        NSString * removeMusicStr = @"remove";
        [self debug:[NSString stringWithFormat:@"asked to remove:\n"]];
        @try {
            int sent = [mainSock sendBytes:[removeMusicStr UTF8String] OfLength:[removeMusicStr length] Index:0];
            int sent2 = [mainSock sendBytes:[[titCB stringValue] UTF8String] ofLength:[[titCB stringValue] length] Index:0];
        } @catch (NSException *e) {
            [self debug:[NSString stringWithFormat:@"%@ Exception (%@)", [e name], [e reason]]];
        }
        [[appDelegate albumTB]
        setStringValue:[NSString stringWithFormat:@"Music Description Removed"]];
    }

    - (void) refreshMD {
        NSString * refreshMusicStr = @"refresh";
        [self debug:[NSString stringWithFormat:@"asked to refresh\n"]];
        [[appDelegate albumTB]
        setStringValue:[NSString stringWithFormat:@"Music Descriptions Refreshed"]];
    }

    - (void) playMD {
        NSString * playMusicStr = @"play";
        ClientSocket *playSock;
        DownloaderThread *downloader;
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        @try {
            playSock = [[ClientSocket alloc] initWithHost:host portNumber:@"9002"];
            [playSock connect];
            int sent = [mainSock sendBytes:[playMusicStr UTF8String] OfLength:[playMusicStr length] Index:0];

            [self debug:[NSString stringWithFormat:@"asked to play:\n"]];;
            downloader = [[DownloaderThread alloc] initWithClient:self  socket:playSock];
        } @catch (NSException *e) {
            [self debug:[NSString stringWithFormat:@"%@ Exception (%@)", [e name], [e reason]]];
        }
        [playSock release];
        [downloader release];
        [pool release];
    }

    - (void) comboBoxSelectionDidChange: (NSNotification*)notification {
        NSComboBox*titCB = [appDelegate titleCB];
        NSString* selected = [titCB objectValueOfSelectedItem];
        [self debug:[NSString stringWithFormat:@"selected title: %s\n", [selected UTF8String]]];

    }

    - (void) debug: (NSString*) aMessage{
        if(DEBUGON){
        NSString * fileName = @"/Users/lindquis/Courses/Cst420/Assigns/" "AssignsF12/Assign3/SampleAssign3/GUIMessages.txt";
        NSFileHandle* fh = [NSFileHandle fileHandleForWritingAtPath: fileName];
        [fh seekToEndOfFile];
        [fh writeData: [aMessage dataUsingEncoding:NSUTF8StringEncoding]];
        [fh closeFile];
        //printf("debug: %s\n", [aMessage UTF8String]);
        }
    }

   @end

客户端套接字.m

#import "ClientSocket.h"

/**
 * SER 321 Foundations of Distributed Applications,
 * based on the simple server and client sockets in C by Jeez.
 * See http://pooh.poly.asu.edu/Cst420
 * @author Christopher Sosa (smoothpinkjazz@gmail.com), ASU Polytechnic, Engineering
 * @version December 2012
 */

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa){
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }
    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

@implementation ClientSocket
- (id) initWithHost: (NSString*) host portNumber: (NSString*) port {
    self = [super init];
    hostName = host;
    [hostName retain];
    portNum = port;
    [portNum retain];
    return self;
}

- (BOOL) connect {
    connected = YES;
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    if ((rv = getaddrinfo([hostName UTF8String], [portNum UTF8String], &hints, &servinfo)) != 0) {
        fprintf(stderr, "client error getting host address: %s\n", gai_strerror(rv));
        connected = NO;
    }
    // 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 error creating socket");
            connected = NO;
            continue;
        }
        int callret = connect(sockfd, p->ai_addr, p->ai_addrlen);
        if (callret == -1) {
            #if defined(WINGS)
            closesocket(sockfd);
            #else
            close(sockfd);
            #endif
            #if defined(WINGS)
            //printf("client failed to connect.\n");
            #else
            inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s);
            printf("client failed to connect to %s\n", s);
            #endif
            //perror("client error connecting");
            connected = NO;
            continue;
        }
        break;
    }
    if (p == NULL) {
        printf("client failed to connect\n");
        connected = NO;
    } else{
        #if defined(WINGS)
        //printf("client connected\n");
        #else
        inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s);
        printf("client connected to %s\n", s);
        #endif
        connected = YES;
    }
    return connected;
}

- (int) sendBytes: (char*) byteMsg OfLength: (int) msgLength Index: (int) at{
    int ret = send(sockfd, byteMsg, msgLength, 0);
    if(ret == -1){
        NSLog(@"client error sending bytes");
    }
    return ret;
}

- (NSString*) receiveBytes: (char*) byteMsg
              maxBytes: (int) max
               beginAt: (int) at {
    int ret = recv(sockfd, byteMsg, max-1, at);
    if(ret == -1){
        NSLog(@"client error receiving bytes");
    }
    byteMsg[ret+at] = '\0';
    NSString * retStr = [NSString stringWithUTF8String: byteMsg];
    return retStr;
}

- (BOOL) close{
    connected = NO;
    return YES;
}

- (void) dealloc {
    [hostName release];
    [portNum release];
    [super dealloc];
}

@end

基本上,我试图将我的 Java 客户端翻译成 Objective-C。ClientSocket.m 文件主要由讲师提供,我做了一些修改。服务器仍然是用 Java 编写的。

有人可以帮忙吗?

4

1 回答 1

2

在我看来,这是一个简单的打字错误!您在调用的函数中拼错了“receive”字样。iOS 在运行时找不到该方法,因此引发无法识别的选择器异常。

identStr = [mainSock recieveBytes:buf maxBytes:MAXDATASIZE beginAt:0];

应该

identStr = [mainSock receiveBytes:buf maxBytes:MAXDATASIZE beginAt:0];

快乐编码!

于 2012-12-12T04:33:52.270 回答