我正在开发 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 编写的。
有人可以帮忙吗?