带有 Linux 套接字的坏文件描述符 write() 坏文件描述符 C

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11258781/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 07:09:05  来源:igfitidea点击:

Bad File Descriptor with Linux Socket write() Bad File Descriptor C

clinuxsocketstcpfile-descriptor

提问by user1336117

I have an interesting problem with write(2) function. PrepareResponseForSetCoordinates function causes bad file descriptor error on write.

我对 write(2) 函数有一个有趣的问题。PrepareResponseForSetCoordinates 函数会导致写入时出现错误的文件描述符错误。

Here is the line of error: perror("ERROR writing to socket"); total output: ERROR writing to socket: Bad file descriptor

这是错误行: perror("ERROR writing to socket"); 总输出:错误写入套接字:错误的文件描述符

I am sure that I have established the connection because PrepareResponseForConnectionTest works like a charm.

我确信我已经建立了连接,因为 PrepareResponseForConnectionTest 就像一个魅力。

Can you have any idea about the reason of the error?

你能知道错误的原因吗?

When I use gcc as compiler there was no problem. After that because of using multiple new cpp sources I am using g++ as compiler and I have this error.

当我使用 gcc 作为编译器时,没有问题。之后,由于使用了多个新的 cpp 源,我使用 g++ 作为编译器,并且出现此错误。

Regards

问候

Here below my code:

下面是我的代码:

#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);  

}

}

Here below you can see the code which run without error:

下面你可以看到运行没有错误的代码:

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);
}

Here is my InitializeConnection function and ConnectToServer function:

这是我的 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;   
}

采纳答案by ciphor

In general, when "Bad File Descriptor" is encountered, it means that the socket file descriptor you passed into the API is not valid, which has multiple possible reasons:

一般情况下,当遇到“Bad File Descriptor”时,说明你传入API的socket文件描述符无效,这有多种可能的原因:

  1. The fd is already closed somewhere.
  2. The fd has a wrong value, which is inconsistent with the value obtained from socket() api
  1. fd 已经在某处关闭了。
  2. fd值错误,与socket() api获取的值不一致

回答by user207421

The value you have passed as the file descriptor is not valid. It is either negative or does not represent a currently open file or socket.

您作为文件描述符传递的值无效。它要么是负数,要么不代表当前打开的文件或套接字。

So you have either closed the socket before calling write()or you have corrupted the value of 'sockfd' somewhere in your code.

因此,您要么在调用之前关闭了套接字,要么write()在代码中的某处损坏了 'sockfd' 的值。

It would be useful to trace all calls to close(), and the value of 'sockfd' prior to the write()calls.

close()write()调用之前跟踪对 的所有调用以及 'sockfd' 的值会很有用。

Your technique of only printing error messages in debug mode seems to me complete madness, and in any case calling another function between a system call and perror()is invalid, as it may disturb the value of errno. Indeed it may have done so in this case, and the real underlying error may be different.

你在调试模式下只打印错误消息的技术在我看来完全是疯了,无论如何在系统调用之间调用另一个函数perror()是无效的,因为它可能会干扰errno. 事实上,在这种情况下它可能已经这样做了,而真正的潜在错误可能会有所不同。

回答by Iman Mirzadeh

I had this error too, my problem was in some part of code I didn't close file descriptor and in other part, I tried to open that file!! use close(fd)system call after you finished working on a file.

我也有这个错误,我的问题是在代码的某些部分我没有关闭文件描述符,而在其他部分,我试图打开那个文件!!处理close(fd)完文件后使用系统调用。