次のように動作する必要があるCでTCPクライアントを実装しようとしています:
- 特定のサーバーへの接続を開く機能
- 確立された接続を介してサーバーに任意のデータを送信する機能、および
- サーバーから任意のデータを受信する機能 (クライアントがサーバーに送信した「質問」への応答と考えてください)。
たとえば、クライアントは任意の HTTP サーバーへの接続を開き、「HEAD」メッセージを送信し、HTTP サーバーから到着した応答を出力できる必要があります。
(私の目標は、日常業務に使用していて、ネットワーク機能が不足している特定のソフトウェア環境用の汎用の「TCP クライアント プラグイン」を作成することです。自分の環境の SDK についてはよく知っていますが、実際には持っていません。ソケットプログラミングの深い経験。)
現在、データの送受信用に 2 つのスレッドがあります。レシーバー スレッド (サーバー アドレスとポートがユーザーによって設定されるとすぐに自動的に開始される) のワークフローは次のとおりです (ここでは、ソケット呼び出しの主なシーケンスについてのみ説明します)。
globalSocket = socket(); // Create socket and store it globally
bind(); // Bind the local port
connect(); // Connect to remote host & port
listen(); // Listen to the socket
while (isAlive) {
select(... &readfds ...); // Check for ready reader descriptors
accept(); // Accept the incoming connection
recv(); // Receive data from server
}
close(); // End the connection
送信側スレッドは非常に単純でglobalSocket
、受信側スレッドによって作成されたを使用してsend()
コマンドを実行します。
ここで問題があります。リモート サーバーへの接続を問題なく開くことができます。任意のデータも問題なく送信できます(実際に送信したデータが問題なくサーバー側に届くことを確認しました)。ただし、サーバーからデータを取得できません。いくつかのテストの後select
、正の値を返すことはないようです。
私は自分のコードで多くの変更を試みました (パラメーターを に変更するselect
、省略するlisten
など)。Beej のガイドをこの日のうちに少なくとも 10 回読み、想像できるすべてのアドホックな変更を試みましたが、動作はまだです。同じ。したがって、特定のコードの抜粋で特定の質問をする前に、この問題に対する私のアプローチが正しかったのか、それとも深刻な概念上の問題を抱えているのかを知りたいと思います。
回答ありがとうございます。
アダム
PS このコード部分は長すぎるため、コメントに投稿できませんでした。select
--サイクルを管理するコード スニペットは次accept
のとおりです。recv
while ( thread->isActive ) {
// Accept connection
timeVal.tv_sec = TIMEOUT_SEC;
timeVal.tv_usec = TIMEOUT_USEC;
FD_ZERO( & fileDescriptor );
FD_SET( socketDescriptor, & fileDescriptor ); // socketDescriptor is the global socket
result = select ( FD_SETSIZE, & fileDescriptor, NULL, NULL, & timeVal );
if ( result > 0 ) {
post ( "select" ); // This line is actually never reached
connectionDescriptor = accept ( socketDescriptor, ( struct sockaddr * ) & clientAddress, & clientLength ); // connectionDescriptor is the local socket created by accept
if ( connectionDescriptor < 0 ) { // Some error happened
outlet_int ( thread->parent->statusOutlet, errno );
} else {
// Receive data
data.clear ( ); // 'data' is an std::vector of chars that stores the incoming data and makes it accessible for the rest of the environment
size = thread->parent->bufferSize;
buffer = new unsigned char [ size ]; // this buffer is used for receiving the data from 'recv'
receivedBytes = 1;
while ( receivedBytes > 0 ) {
receivedBytes = recv ( connectionDescriptor, ( char * ) buffer, size, 0 );
if ( receivedBytes < 0 ) { // Socket error
outlet_int ( thread->parent->statusOutlet, errno );
}
data.insert ( data.end ( ), buffer, buffer + receivedBytes );
}
delete [ ] buffer;
#ifdef WIN_VERSION
closesocket ( connectionDescriptor );
#else
close ( connectionDescriptor );
#endif
// Output received data
... blah ... blah ... blah
}
}
}