[解決済み】Linuxソケットのwrite()でBad File Descriptorが発生するC
2022-02-18 20:40:05
質問
write(2) 関数で面白い問題があります。PrepareResponseForSetCoordinates関数は、書き込み時に不正なファイル記述子エラーを引き起こします。
以下はエラーの行です。 perror("ERROR writing to socket"); の合計が出力されます。 ERROR writing to socket: 不正なファイル記述子
PrepareResponseForConnectionTestが魅力的に動作するので、私は接続を確立したことを確信しています。
エラーの原因について、何か心当たりはありますか?
コンパイラとしてgccを使用しているときは問題がありませんでした。その後、複数の新しいcppソースを使用したため、コンパイラとしてg++を使用していますが、このエラーが発生します。
ご挨拶
以下、私のコードです。
#define MAX_PMS_MESSAGE_LEN (4096)
unsigned char baCommBuffer[MAX_PMS_MESSAGE_LEN];
unsigned char PrepareResponseForSetCoordinates(void)
{
unsigned char baTempBuff[255]={0};
unsigned short bCnt=0,i=0,bCsum=0,bCnt2=0;
time_t lEpochTime;
time_t lSessionTime;
memset(baTempBuff,0,sizeof(baTempBuff));
memset(baCommBuffer,0,sizeof(baCommBuffer));
bzero(baCommBuffer,MAX_PMS_MESSAGE_LEN);
bzero(baTempBuff,sizeof(baTempBuff));
lEpochTime = time(NULL);
baCommBuffer[bCnt++] = START_CHAR;
baCommBuffer[bCnt++] = START_CHAR;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
sprintf((char*)baTempBuff,"%ld",(unsigned long)lEpochTime);
memcpy(baCommBuffer+bCnt,baTempBuff,10);
bzero(baTempBuff,sizeof(baTempBuff));
bCnt+=10;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
// lSessionTime = time(NULL);
if(SPMSMessage.lSessionID)
lSessionTime = SPMSMessage.lSessionID;
else
lSessionTime=lEpochTime;
sprintf((char*)baTempBuff,"%ld",(unsigned long)lSessionTime);
memcpy(baCommBuffer+bCnt,baTempBuff,10);
bzero(baTempBuff,sizeof(baTempBuff));
bCnt+=10;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = PMC_ID;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = PMS_ID;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = 'R';
baCommBuffer[bCnt++] = 'E';
baCommBuffer[bCnt++] = 'P';
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = 'C';
baCommBuffer[bCnt++] = 'O';
baCommBuffer[bCnt++] = 'O';
baCommBuffer[bCnt++] = 'S';
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
if(SPMSMessage.bParam== SET_COOR_CAM1_PARAM)
{
baCommBuffer[bCnt++] = '2';
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = 'O';
baCommBuffer[bCnt++] = 'N';
baCommBuffer[bCnt++] = 'E';
baCommBuffer[bCnt++] = PARAMETER_SEPERATOR;
baCommBuffer[bCnt++] = 'A';
baCommBuffer[bCnt++] = 'C';
baCommBuffer[bCnt++] = 'K';
}
else if(SPMSMessage.bParam== SET_COOR_CAM2_PARAM)
{
baCommBuffer[bCnt++] = '2';
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = 'T';
baCommBuffer[bCnt++] = 'W';
baCommBuffer[bCnt++] = 'O';
baCommBuffer[bCnt++] = PARAMETER_SEPERATOR;
baCommBuffer[bCnt++] = 'A';
baCommBuffer[bCnt++] = 'C';
baCommBuffer[bCnt++] = 'K';
}
else
{
baCommBuffer[bCnt++] = '1';
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = 'N';
baCommBuffer[bCnt++] = 'A';
baCommBuffer[bCnt++] = 'C';
baCommBuffer[bCnt++] = 'K';
}
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = '*';
memset(baTempBuff,0,sizeof(baTempBuff));
bCsum = CalculateCheckSum(baCommBuffer);
sprintf((char*)baTempBuff,"%.2X",bCsum);
memcpy(baCommBuffer+bCnt,baTempBuff,2);
bzero(baTempBuff,sizeof(baTempBuff));
bCnt+=2;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = END_CHAR;
baCommBuffer[bCnt++] = END_CHAR;
#ifdef _DEBUG_DEEP_DETAILED
if(EDebugDeepDetail<GetDebugLevelOfPMC())
{
printf("WILL BE sent: %s uzunluk:%d\n", baCommBuffer,bCnt);
sprintf(caLogStr,"WILL BE sent: %s uzunluk:%d\n", baCommBuffer,bCnt);
PrintToLogFile(caLogStr);
memset(caLogStr,0,MAX_LOG_STRLEN);
}
#endif
if((ETcpConnectionState== ETcpStateConnected) || (ETcpConnectionState== ETcpStateConnectedAndWaitingToWrite) )
{
if (write(sockfd,baCommBuffer,bCnt) < 0)
{
#ifdef _DEBUG_DETAILED
if(EDebugDetail<GetDebugLevelOfPMC())
{
perror("ERROR writing to socket");
PrintToLogFile("ERROR writing to socket");
}
#endif
return 0;
}
#ifdef _DEBUG_DEEP_DETAILED
if(EDebugDeepDetail<GetDebugLevelOfPMC())
{
printf("sent: %s uzunluk:%d\n", baCommBuffer,bCnt);
sprintf(caLogStr,"sent: %s uzunluk:%d\n", baCommBuffer,bCnt);
PrintToLogFile(caLogStr);
memset(caLogStr,0,MAX_LOG_STRLEN);
}
#endif
}
else
{
#ifdef _DEBUG_DETAILED
if(EDebugDetail<GetDebugLevelOfPMC())
{
PrintToLogFile("Henüz Bağlantı Yok\n");
}
#endif
return 0;
}
return (bCnt);
}
以下は、エラーなしで実行されたコードの例です。
unsigned char PrepareResponseForConnectionTest(void)
{
unsigned char baTempBuff[20]={0};
unsigned char bCnt=0,i=0,bCsum=0;
time_t lEpochTime;
time_t lSessionTime;
memset(baTempBuff,0,sizeof(baTempBuff));
memset(baCommBuffer,0,sizeof(baCommBuffer));
bzero(baCommBuffer,MAX_PMS_MESSAGE_LEN);
bzero(baTempBuff,sizeof(baTempBuff));
lEpochTime = time(NULL);
baCommBuffer[bCnt++] = START_CHAR;
baCommBuffer[bCnt++] = START_CHAR;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
sprintf((char*)baTempBuff,"%ld",(unsigned long)lEpochTime);
memcpy(baCommBuffer+bCnt,baTempBuff,10);
bzero(baTempBuff,sizeof(baTempBuff));
bCnt+=10;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
lSessionTime = SPMSMessage.lSessionID;
sprintf((char*)baTempBuff,"%ld",(unsigned long)lSessionTime);
memcpy(baCommBuffer+bCnt,baTempBuff,10);
bzero(baTempBuff,sizeof(baTempBuff));
bCnt+=10;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = PMC_ID;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = PMS_ID;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = 'R';
baCommBuffer[bCnt++] = 'E';
baCommBuffer[bCnt++] = 'P';
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = 'C';
baCommBuffer[bCnt++] = 'O';
baCommBuffer[bCnt++] = 'N';
baCommBuffer[bCnt++] = 'T';
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = '1';
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = 'A';
baCommBuffer[bCnt++] = 'C';
baCommBuffer[bCnt++] = 'K';
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = '*';
memset(baTempBuff,0,sizeof(baTempBuff));
bCsum = CalculateCheckSum(baCommBuffer);
sprintf((char*)baTempBuff,"%.2X",bCsum);
memcpy(baCommBuffer+bCnt,baTempBuff,2);
bzero(baTempBuff,sizeof(baTempBuff));
bCnt+=2;
baCommBuffer[bCnt++] = PACKET_SEPERATOR;
baCommBuffer[bCnt++] = END_CHAR;
baCommBuffer[bCnt++] = END_CHAR;
if((ETcpConnectionState== ETcpStateConnected) || (ETcpConnectionState== ETcpStateConnectedAndWaitingToWrite) )
{
if (write(sockfd,baCommBuffer,bCnt) < 0)
{
perror("ERROR writing to socket\n");
PrintToLogFile("ERROR writing to socket\n");
}
#ifdef _DEBUG_DEEP_DETAILED
if(EDebugDeepDetail<GetDebugLevelOfPMC())
{
printf("sent: %s uzunluk:%d\n", baCommBuffer,bCnt);
sprintf(caLogStr,"sent: %s uzunluk:%d\n", baCommBuffer,bCnt);
PrintToLogFile(caLogStr);
memset(caLogStr,0,MAX_LOG_STRLEN);
}
#endif
return 0;
}
else
{
#ifdef _DEBUG_DETAILED
if(EDebugDetail<GetDebugLevelOfPMC())
{
PrintToLogFile("There is no connection yet\n");
}
#endif
//return 0;
}
//printf("\n\n");
return (bCnt);
}
InitializeConnection関数とConnectToServer関数は以下の通りです。
void InitializeTcpConnection(int argc, char *argv[])
{
int optval;
socklen_t optlen = sizeof(optval);
ETcpConnectionState = ETcpStateNotConnected;
if (argc < 3)
{
fprintf(stderr,"usage: %s hostname_or_ip port\n", argv[0]);
#ifdef _DEBUG_PROCESS
if(EDebugProcess<GetDebugLevelOfPMC())
{
sprintf(caLogStr,"usage: %s hostname_or_ip port\n", argv[0]);
PrintToLogFile(caLogStr);
memset(caLogStr,0,MAX_LOG_STRLEN);
}
#endif
exit(0);
}
portno = atoi(argv[2]);
/* int socket(domain,type,protocol)
* socket creates an endpoint for communication and returns a descriptor
* AF_INET: ARPA Internet protocols
* SOCK_STREAM: sequenced, two way connection based byte streams
*
* return: Socket returns a non-negative descriptor on success.
* On failure it returns -1 and sets errno to indicate the error
* */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
#ifdef _DEBUG_PROCESS
if(EDebugProcess<GetDebugLevelOfPMC())
{
perror("ERROR creating socket");
PrintToLogFile("ERROR creating socket\n");
}
#endif
exit(1);
}
/**/
/* Set the option active */
optval = 1;
optlen = sizeof(optval);
if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0)
{
#ifdef _DEBUG_PROCESS
if(EDebugProcess<GetDebugLevelOfPMC())
{
perror("setsockopt()");
PrintToLogFile("ERROR creating socket\n");
}
#endif
close(sockfd);
exit(EXIT_FAILURE);
}
#ifdef _DEBUG_PROCESS
if(EDebugProcess<GetDebugLevelOfPMC())
{
printf("SO_KEEPALIVE set on socket\n");
PrintToLogFile("SO_KEEPALIVE set on socket\n");
}
#endif
/* Check the status again */
if(getsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {
#ifdef _DEBUG_PROCESS
if(EDebugProcess<GetDebugLevelOfPMC())
{
perror("getsockopt()");
PrintToLogFile("getsockopt()");
}
#endif
close(sockfd);
exit(EXIT_FAILURE);
}
#ifdef _DEBUG_PROCESS
if(EDebugProcess<GetDebugLevelOfPMC())
{
printf("SO_KEEPALIVE is %s\n", (optval ? "ON" : "OFF"));
}
#endif
#ifdef _DEBUG_PROCESS
if(EDebugProcess<GetDebugLevelOfPMC())
{
PrintToLogFile("Setting socket for reusability\n");
}
#endif
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) == -1)
{
#ifdef _DEBUG_PROCESS
if(EDebugProcess<GetDebugLevelOfPMC())
{
perror("setsockopt");
PrintToLogFile("Setting socket option error\n");
}
#endif
exit(1);
}
/*********/
//get the address info by either host name or IP address
SetTcpServerIpAddress(argv[1]);
server = gethostbyname(argv[1]);
if (server == NULL)
{
#ifdef _DEBUG_PROCESS
if(EDebugProcess<GetDebugLevelOfPMC())
{
PrintToLogFile("ERROR, no such host\n");
}
#endif
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
//serv_addr.sin_port: unsigned short
//htons converts the unsigned short hostshort from host byte order to network byte order
serv_addr.sin_port = htons(portno);
ETcpConnectionState = ETcpStateWaitingForConnection;
}
int ConnectToServer(void)
{
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{
#ifdef _DEBUG_DETAILED
if(EDebugDetail<GetDebugLevelOfPMC())
{
PrintToLogFile("ERROR connecting");
}
#endif
return 1; // connection error
//exit(1);
}
else
{
#ifdef _DEBUG_DETAILED
if(EDebugDetail<GetDebugLevelOfPMC())
{
PrintToLogFile("connection established\n");
}
#endif
#ifndef PMS_COMM_POLL_MODE
#ifdef _DEBUG_DETAILED
if(EDebugDetail<GetDebugLevelOfPMC())
{
PrintToLogFile("State is non poll mode\n");
}
#endif
ETcpConnectionState = ETcpStateConnected;
#endif
#ifdef PMS_COMM_POLL_MODE
#ifdef _DEBUG_DETAILED
if(EDebugDetail<GetDebugLevelOfPMC())
{
PrintToLogFile("State is poll mode\n");
}
#endif
ETcpConnectionState = ETcpStateConnectedAndWaitingToRead;
#endif
SendRequestToGetImageUploadInfo();
}
return 0;
}
解決方法は?
一般に、"Bad File Descriptor"が発生した場合、APIに渡したソケットファイル記述子が有効でないことを意味し、その理由は複数考えられます。
- fdは既にどこかで閉じられている。
- fd の値が間違っており、socket() api から取得した値と矛盾している。
関連
-
[解決済み】Valgrind - strcpyのサイズ1の無効な書き込み
-
[解決済み】組み込み関数「malloc」の暗黙の宣言の非互換性
-
[解決済み] (.text+0x20): `main'への未定義の参照と関数への未定義の参照
-
[解決済み】式は、単純なポインタ演算を使用して完全なオブジェクト型へのポインタでなければなりません【重複】。
-
[解決済み】C言語におけるファイルスコープでの可変長配列の変更
-
[解決済み】コンパイラの警告 - 真理値として使用される代入の周囲に括弧を付けることを推奨する
-
[解決済み】インクリメントオペランドとして lvalue が必要です。
-
[解決済み] '{'トークンの前に期待される式
-
[解決済み】エラー:呼び出されたオブジェクトは、関数または関数ポインタではない
-
[解決済み] パイプで "tee "を使用しているときに、標準エラーをファイルに書き込むにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】エラー:cの入力の最後に期待される宣言またはステートメント
-
[解決済み] clang: error: linker command failed with exit code 1が表示されるのはなぜですか?
-
[解決済み】 switch case: error: case label does not reduce to an integer constant
-
[解決済み] struct has no member named
-
[解決済み】ヒープ割り当てで初期化されていない値が作成された
-
[解決済み】C 未知の型名「my_structure」。
-
[解決済み】警告:引数「互換性のないポインタ型から」を渡す[デフォルトで有効]。
-
[解決済み】インクリメントオペランドとして lvalue が必要です。
-
[解決済み】未定義参照 makefile が間違っているのかも?
-
[解決済み】C言語のフォーマット文字列でデータ引数が使用されない [重複]。