[解決済み] Linux Socket write() によるBad File Descriptor C
2022-03-16 13:30:26
質問
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 から取得した値と矛盾している。
関連
-
[C] レポートエラー 代入の左オペランドとしてlvalueが必要
-
エラー: 宣言されていない識別子 'bool' の使用と C コンパイラでの問題点
-
警告: 'struct XXX' はパラメータリストの内部で宣言されています。
-
[解決済み] Valgrind が初期化されていないバイトについて警告する
-
[解決済み] C言語で%sを正しく使う - 超基本レベル
-
[解決済み] Windows用Cコンパイラ?[クローズド]
-
[解決済み] Linuxカーネルにおけるcontainer_ofマクロの理解
-
[解決済み] ソケットアクセプト - "開かれているファイルが多すぎる"
-
[解決済み] Cコードの単体テスト【終了しました
-
[解決済み] パイプで "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 実装 サイバーパンク風ボタン
おすすめ
-
g++が内部・外部コマンドソリューションとして認識されない、MinGWを初めて使うときの落とし穴
-
initializer element is not constant "というエラーが表示されるのですが?
-
警告: 'struct XXX' はパラメータリストの内部で宣言されています。
-
[解決済み] stdinとSTDIN_FILENOの違いは何ですか?
-
[解決済み] CコードでEOFを表現する?
-
[解決済み] C言語で関数型プログラミングを行うためのツールにはどのようなものがありますか?
-
[解決済み] なぜC言語では構造体を頻繁にtypedefする必要があるのですか?
-
[解決済み] フリーは、どのように無料化を知っているのですか?
-
[解決済み] C言語で "unsigned long "をprintfする方法は?
-
[解決済み] LD_PRELOADのトリックとは何ですか?