別のTCPソケットの問題に直面しています。私は同様の問題に対する答えをたくさんの質問に読み通しましたが、私の問題はどういうわけか異なります。
JavaクライアントとC++サーバーがあります。別のマシンを使用するまでは、すべてが期待どおりに進みます(これまでの他の問題と同じです)。クライアントからのメッセージがTCPバッファーでスタックしているようです。最終的にソケットを閉じると、すべてがサーバーに送信されます。ただし、これらの単一メッセージは制御メッセージであるため、すぐに送信する必要があります。私が読んだ限り、これは予想される動作ですが、信頼できる制御メッセージを送信するにはどうすればよいですか。
メッセージを強制的に送信する方法はありますか?(何も送信せずに、ソケットを数分間開いたままにしておくことができます。)
何か問題がありますか?(次のコードを参照してください)
REALフラッシュを実行するには、毎回ソケットを閉じる必要がありますか?
代わりにUDPを使用し、追加のプロトコル作業を行う必要がありますか?
Javacode:
mSocketSend = new Socket();
mSocketSend.connect(new InetSocketAddress(mServerIp, mSocketPortSend), mTimeOut);
PrintWriter pw = new PrintWriter(mSocketSend.getOutputStream(), true);
pw.println(data);
C ++コード:
opening socket...(i leave that)
char* buffer = new char[1024];
int rc = recv(mConnectedSocket, buf, 1024, 0);
もっと欲しいなら。書いてください。私はほとんどすべてを省きました。^^私はそれが適切だとは思いません。コミュニケーションは通常うまくいきました..エラーはまったくありませんでした。つまり、これだけのTCPBufferです。
区切り文字やメッセージの長さなどがあるはずです。しかし実際には、送信されないメッセージの長さは役に立ちません。^^
ご協力いただきありがとうございます。
編集#01コードの全体:
mSocket->createSocketServer(22);
char* buffer = new char[1024];
while(true){
int numberBytes = mSocket->receiveChars(buffer, 1024);
if (numberBytes > 0){
uninterestingHandlingFunction(buffer);
}else{
mSocket->createSocketServer(22);
}
}
bool Socket::createSocketServer(u_short port)
{
if (mConnectedSocket != INVALID_SOCKET)
{
closesocket(mConnectedSocket);
}
if (s == INVALID_SOCKET)
{
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,0), &wsa) != 0)
return 0;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
return 0;
SOCKADDR_IN addr;
memset(&addr, 0, sizeof(SOCKADDR_IN));
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
addr.sin_addr.s_addr=ADDR_ANY;
if (bind(s, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
s = INVALID_SOCKET;
} else if (listen(s, 10) == SOCKET_ERROR)
{
s = INVALID_SOCKET;
}
if (s == INVALID_SOCKET)
{
closesocket(s);
return 0;
}
}
mConnectedSocket = accept(s, NULL, NULL);
if (mConnectedSocket == INVALID_SOCKET)
{
closesocket(s);
return 0;
}
return 1;
}
int Socket::receiveChars(char* buf, unsigned maxSize)
{
if (mConnectedSocket == INVALID_SOCKET)
return -1;
int rc = recv(mConnectedSocket, buf, maxSize, 0);
if (rc == SOCKET_ERROR)
{
std::cout << "Socket: error " << WSAGetLastError() << std::endl;
}
return rc;
}
あなたはそれが欲しかった…。
編集#2もう一度試してみてください
私が試したことが他にもいくつかあります。最初:この問題は、実際のネットワークを介して毎回接続されているデバイスでは発生しません。->クライアントとサーバーの完全な再起動->問題は発生しません->クライアントとサーバーの完全な再起動->問題が発生します
悲しいことに、私はこの習慣から何を取るべきかわかりません。
私が偶然見つけたもう1つのことは、バインドおよびリッスンソケット(コードSOCKET)です。このソケットは接続をリッスンし、作業スレッドが新しい接続を必要とする場合(起動時または前の接続が閉じた場合)、ソケットsはrecvのためにmConnectedSocketに次のキュー接続を提供し、他の接続は処理中にバックログされます。Javaビューから:ソケットが接続されています(デバイスA)。次のソケット(デバイスB)が接続を試みます。->接続の成功(これが実際に発生した場合はコードで適切に制御されます)->その後に自然な問題でデータを送信します。(ソケットはまだc ++側のバックログにあります)
さて、これは私が経験した習慣に変えるのは難しいです。自分の考えを表現しようと思います。Javaside:PrintWriterが作成されます。データが供給され、フラッシュされます。接続が完全に確立されていないため(C ++側に追加のconnectedSocketはありません)。フラッシュが機能しません。そして、onCloseは、ソケットが最終的にその内容をフラッシュします。
もしそう思うなら、黙ってくださいと言ってください。「接続がバックログされている」が実際に実装で何を意味するのか、私にはよくわかりません^^
接続ごとに新しいスレッドを開く必要があることはわかっていますが、現時点ではできません。したがって、このサーバーコードに固執します。