異なるスレッドから同時に安全であるべきだと読みましたが、私のプログラムには奇妙な動作があり、何が問題なのかわかりません。
クライアントソケットと通信する同時スレッドがあります
- ソケットへの送信を行うもの
- 同じソケットから select を実行してから recv を実行するもの
私がまだ送信しているので、クライアントはすでにデータを受信してソケットを閉じています。同時に、そのソケットで select と recv を実行していますが、(閉じているため) 0 を返すため、このソケットを閉じます。ただし、送信はまだ返されていません...そして、このソケットで close を呼び出しているため、send 呼び出しは EBADF で失敗します。
ソケットを閉じた後にデータを出力したので、クライアントがデータを正しく受信したことがわかり、正しいです。ただし、私の側では、send 呼び出しがまだエラー (EBADF) を返しているので、失敗しないように修正したいと考えています。
これは常に起こるわけではありません。おそらく40%の確率で発生します。私はどこでもスリープを使用しません。送信や受信などの間に一時停止する必要がありますか?
ここにいくつかのコードがあります:
送信:
while(true)
{
// keep sending until send returns 0
n = send(_sfd, bytesPtr, sentSize, 0);
if (n == 0)
{
break;
}
else if(n<0)
{
cerr << "ERROR: send returned an error "<<errno<< endl; // this case is triggered
return n;
}
sentSize -= n;
bytesPtr += n;
}
受信:
while(true)
{
memset(bufferPointer,0,sizeLeft);
n = recv(_sfd,bufferPointer,sizeLeft, 0);
if (debug) cerr << "Receiving..."<<sizeLeft<<endl;
if(n == 0)
{
cerr << "Connection closed"<<endl; // this case is triggered
return n;
}
else if (n < 0)
{
cerr << "ERROR reading from socket"<<endl;
return n;
}
bufferPointer += n;
sizeLeft -= n;
if(sizeLeft <= 0) break;
}
クライアントでは、同じ受信コードを使用してから、ソケットで close() を呼び出します。次に、私の側では、受信呼び出しから 0 を取得し、ソケットで close() も呼び出します。その後、送信が失敗します。まだ終わらない!? しかし、私のクライアントはすでにデータを取得しています!