문제

나는이 웹 사이트 에서이 주제에 관한 많은 질문을 읽었지만 그들은 내 질문에 조용히하지 않았다. 내 목표 나 배경에 대해 ###이 될 수 없다면 질문으로 건너 뛰십시오.

내 목표

Mac OS X 10.4+에서 실행될 수있는 서버를 구축하는 것입니다. 나중에는 Windows XP/Vista로 포트를 포장하는 것입니다 (아직 어떻게 해야할지 모르지만 나중에 문제가됩니다).

그런 다음 iPhone이 서버를 실행중인 컴퓨터 이름 (WiFi를 통해)을 볼 수있는 클라이언트가되도록하십시오. 그런 다음 iPhone 사용자는 컴퓨터 이름을 선택하여 해당 컴퓨터의 서버에 연결할 수 있습니다.

그 후 그들은 간단한 문자 메시지를 서로 보낼 수 있습니다. 예를 들어, iPhone은 '노크 노크'를 보내고 서버는 '누가 있는가?'라고 응답합니다. 또는 간단한 클라이언트 : 'Ping', 서버 응답 'Pong'은 잘 작동합니다.

배경

나는 과거에 소켓을 사용했지만 winsocket.dll의 Visual Basic 6에서만 TCP/IP 서버를 만드는 것은 매우 쉬웠습니다.

server.host = localhost;
server.port = 12203;
server.listen(); 

클라이언트와 함께 연결하려면 다음을 수행해야했습니다.

client.connect(localhost, 12203);

Connect, Close, DataArrival 등과 같은 콜백이있었습니다.

아마도 iPhone의 경우 라이브러리가 작성되어 있지만이 간단한 응용 프로그램을 직접 작성하기가 어렵습니까? 연구를 한 후 CFNetwork, CFHost, CFSocket, CFStream 영역을 살펴 봐야한다는 것을 이해합니다.

의문

튜토리얼을 안내하거나 iPhone에 두 개의 버튼이있는 코드를 게시 할 수있는 사람이 있습니까? [시작 서버] 및 [서버에 연결] 첫 번째가 특정 포트에서 TCP/IP 서버를 시작하고 두 번째는 연결합니다.

연결이 이루어진 후 서버가 수신 한 후 서버에 간단한 'Ping'Message를 보내는 코드도 클라이언트에'Pong'Message로 응답합니다.

정말 도움이 될 것입니다. 그러나 어쩌면 나는 여기에 많은 것을 요구하고 있습니다.

도움이 되었습니까?

해결책

이 튜토리얼 채팅 샘플 앱을 만들려면 매우 잘 작동하며 매우 간단합니다 (나와 같은 모든 iPhone 멍청이는 시뮬레이터 모드에서도 외부 소켓 서버에 연결됩니다).

소켓 서버에 대해 이야기하도록 조정했으며 매력처럼 작동합니다. 이것은 테스트 코드이므로 느슨한 끝에 대한 실질적인 관심이 없습니다. 하나의 메시지 (로그온 ID) 만 보내고 콘솔에 표시되는 답변을받습니다.

//
//  ViewController.m
//  zdelSocketTest01a
//
//

#import "ViewController.h"



@implementation ViewController
@synthesize inputNameField;
@synthesize joinView;

- (void)initNetworkCommunication {

    uint portNo = 5555;
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"227.3.4.56", portNo, &readStream, &writeStream);
    inputStream = (__bridge NSInputStream *)readStream;
    outputStream = (__bridge NSOutputStream *)writeStream;

    [inputStream setDelegate:self];
    [outputStream setDelegate:self];

    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream open];
    [outputStream open];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self initNetworkCommunication];
    messages = [[NSMutableArray alloc] init];
}

- (void)viewDidUnload
{
    [self setInputNameField:nil];
    [self setJoinView:nil];
    [self setJoinView:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (IBAction)joinChat:(id)sender {

    NSString *response  = [NSString stringWithFormat:@"logon,%@", inputNameField.text];
    NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
    [outputStream write:[data bytes] maxLength:[data length]];

}
/*
 - (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
 NSLog(@"stream event %i", streamEvent);
 }
 */

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
    typedef enum {
        NSStreamEventNone = 0,
        NSStreamEventOpenCompleted = 1 << 0,
        NSStreamEventHasBytesAvailable = 1 << 1,
        NSStreamEventHasSpaceAvailable = 1 << 2,
        NSStreamEventErrorOccurred = 1 << 3,
        NSStreamEventEndEncountered = 1 << 4
    };
    uint8_t buffer[1024];
    int len;

    switch (streamEvent) {

        case NSStreamEventOpenCompleted:
            NSLog(@"Stream opened now");
            break;
        case NSStreamEventHasBytesAvailable:
            NSLog(@"has bytes");
            if (theStream == inputStream) {
                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);
                        }
                    }
                }
            } else {
                NSLog(@"it is NOT theStream == inputStream");
            }
            break;
        case NSStreamEventHasSpaceAvailable:
            NSLog(@"Stream has space available now");
            break;


        case NSStreamEventErrorOccurred:
            NSLog(@"Can not connect to the host!");
            break;


        case NSStreamEventEndEncountered:

            [theStream close];
            [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

            break;

        default:
            NSLog(@"Unknown event %i", streamEvent);
    }

}
/*
 - (void) messageReceived:(NSString *)message {

 [messages addObject:message];
 [self.tView reloadData];

 }
 */

@end

ViewController.h 파일에는 포함됩니다

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <NSStreamDelegate>
@property (weak, nonatomic) IBOutlet UITextField *inputNameField;
@property (weak, nonatomic) IBOutlet UIView *joinView;
- (IBAction)joinChat:(id)sender;


@end
NSInputStream *inputStream;
NSOutputStream *outputStream;
NSMutableArray * messages;

Noobs Only : 컨트롤을 눌러 객체를 코드 창으로 드래그하여 버튼과 텍스트 필드를 연결해야합니다. 그렇게하면 위의 속성이 자동으로 생성됩니다. 확인하다 이 비디오 튜토리얼 당신이 그루터기를받는다면

Noobs 만 2 :이 소켓은 Xcode의 콘솔 창에서 출력됩니다. Xcode 창의 오른쪽 상단 코너에서 숨기기 또는 디버그 영역을 클릭하십시오 (필요한 경우 도움을 요청하십시오).

스노우 레오파드 용 Xcode 4.2를 사용하여 2GB 메모리가 장착 된 MacBook에서 구축 및 테스트 (시뮬레이터 및 장치).

다른 팁

다음을 권장합니다.코코아 비동기 소켓

사이트에는 기본 예제 프로젝트가 있습니다. 나는 그 프레임 워크로 일하는 좋은 성공을 거두었습니다.

서버가 이미 시작되기를 원하고 "서버에 연결"버튼 만 필요로하고 "핑"이 필요합니다. 그렇지 않으면 서버 상자에 "시작 서버 시작"메시지에 응답하고 서버를 시작하는 별도의 프로세스가 필요합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top