iPhone TCP / IPソケットサーバー/クライアントプログラム
-
08-07-2019 - |
質問
このウェブサイトでこの主題に関する多くの質問を読みましたが、彼らは私の質問に静かに答えませんでした。私の目標や背景について###になれない場合は、質問にスキップしてください。
マイゴール
Mac OS X 10.4以降で実行できるサーバーを構築し、Windows XP / Vistaに移植することです(まだその方法はわかりませんが、それは後の問題です)。
次に、iPhoneを、サーバーを実行しているコンピューター名を(WiFiを介して)表示できるクライアントにします。 iPhoneのユーザーは、コンピューター名を選択して、そのコンピューター上のサーバーに接続できます。
その後、彼らは簡単なテキストメッセージを互いに送信できます。たとえば、iPhoneは「Knock Knock」を送信し、サーバーは「Who is there?」と応答します。または、単純なクライアント:「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に2つのボタンがあるコードを投稿できる人はいますか。 [サーバーの起動]と[サーバーへの接続]では、最初のサーバーが特定のポートでTCP / IPサーバーを起動し、2番目のサーバーがそれに接続します。
接続が確立された後、サーバーがこれを受信した後に単純な「Ping」メッセージをサーバーに送信するコードも、クライアントに「Pong」メッセージで応答します。
それは本当に役立つでしょう。しかし、多分私はここに多くを求めています。
解決
このチュートリアルチャットサンプルアプリを作成するのは非常にうまく機能し、非常に簡単です(私のようなiphone noobは、シミュレータモードでも外部ソケットサーバーに接続できます)。
iはソケットサーバーと通信するように調整しました。これはテストコードであるため、ルーズエンドに大きな懸念はありません。 1つのメッセージ(ログオン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のみ:Ctrlキーを押しながらオブジェクトをコードウィンドウにドラッグして、ボタンとテキストフィールドをリンクする必要があります。これを行うと、上記のプロパティが自動的に作成されます。困惑している場合は、このビデオチュートリアルを確認してください
NOOBSのみ2:このソケットは、XCODEのコンソールペインに出力されます。 Xcodeウィンドウの右上隅で、[デバッグエリアの非表示または表示]をクリックします(必要に応じて助けを求めてください)。
Snow Leopardにxcode 4.2を使用して、2GBメモリのMacbookで構築およびテスト(シミュレーターとデバイス)。
他のヒント
次のことをお勧めします。 Cocoa非同期ソケット
サイトには、開始するための基本的なサンプルプロジェクトもあります。このフレームワークでの作業は成功しました。
サーバーを既に起動したい場合は、「サーバーに接続」だけが必要です。ボタン、[Ping]の順にクリックします。そうでない場合は、「Start Server」に応答するサーバーボックス上に別のプロセスが必要です。メッセージを送信してサーバーを起動します。