私は CFNetwork と協力して iPad 用のクライアント アプリケーションを作成しました。これは小さなアプリケーションであり、派手なものではありません。
これは、サーバーへの接続を作成する方法です(Windowsで実行)。
- (void) startConnection
{
char ip[] = "192.168.0.244";
NSString *ipAddress = [[NSString alloc] initWithCString:ip];
/* Build our socket context; this ties an instance of self to the socket */
CFSocketContext CTX = { 0, self, NULL, NULL, NULL };
/* Create the server socket as a TCP IPv4 socket and set a callback */
/* for calls to the socket's lower-level connect() function */
TCPClient = CFSocketCreate(NULL, PF_INET, SOCK_STREAM, IPPROTO_TCP,
kCFSocketDataCallBack, (CFSocketCallBack)DataCallBack, &CTX);
if (TCPClient == NULL)
return;
/* Set the port and address we want to listen on */
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);// PORT = 5001
addr.sin_addr.s_addr = inet_addr([ipAddress UTF8String]);
CFDataRef connectAddr = CFDataCreate(NULL, (unsigned char *)&addr, sizeof(addr));
CFSocketConnectToAddress(TCPClient, connectAddr, -1);
CFRunLoopSourceRef sourceRef =
CFSocketCreateRunLoopSource(kCFAllocatorDefault, TCPClient, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes);
CFRelease(sourceRef);
CFRunLoopRun();
}
ご覧のとおり、サーバー ソケットを作成するときに、サーバーからの着信データをリッスンするコールバックを登録します。
次に、CFRunLoopAddSource(...) および CFRunLoopRun() メソッドを使用して、このコールバックをバックグラウンドでリッスンします。
さて、これが私の send メソッドの外観です
- (void) send
{
if (TCPClient == NULL)
return;
Byte byteData[3];
for (int i = 1; i <= 25; i++) {
receivedLastAnswer = NO;
globalPos = i;
byteData[0] = i;
byteData[1] = 4;
byteData[2] = 0;
int len = 3;//strlen(byte)+1;
CFDataRef refData = CFDataCreate(kCFAllocatorDefault, byteData, len);
CFSocketSendData(TCPClient, NULL, refData, 0);
while (!receivedLastAnswer) {
//this while is to wait until a response is send by the server
}
}
}
私がやりたいことは、サーバーにコマンドを送信し (表示される 3 バイトの配列がコマンドです)、次のコマンドを送信する前にサーバーが応答するのを待つことです。これを行うには、しばらく使用します。変数「receivedLastAnswer」は私の DataCallBack メソッドが呼び出されたときに設定されるフラグ。サーバーが応答すると、コールバックが呼び出され、フラグが true に設定されるため、while が終了し、次のコマンドが送信されます。
もちろん、これは私がコードを残すつもりの方法ではありません。これはテスト用であり、それが機能するかどうかを確認するためのものです。後で、サーバーが応答しない場合に備えて、タイムアウト条件という別の条件を while に追加する必要があります。まったく。
さて、私の問題は、私のアプリケーションであるクライアントがコールバック メソッドを起動していないため、無限に循環することです。コールバックを発生させない理由は、while サイクルでアプリケーションがビジーであるためだと思います。実際、サイクルを削除すると、コールバックが発生しますが、コールバック メソッドが想定されていないため、これは意味がありません。別のスレッドで実行されていること (それが CFRunLoopRun() の目的ではありませんか?) であり、別のスレッドで実行されているため、メイン スレッドがサイクル内にあるかどうかは問題ではありません。または、これがどのように機能するかを完全に誤解しています。 ?
また、while サイクルではなく Sleep() 関数を使用してみましたが、同じで、コールバックは発生しません。
なぜこれが起こっているのか、どうすればこれを達成できるのか分かりますか?
ありがとう。