Slechte bestandsdescriptor met Linux Socket write() Slechte bestandsdescriptor C

Ik heb een interessant probleem met de functie write(2). De functie PrepareResponseForSetCoordinates veroorzaakt een fout in de bestandsdescriptor bij het schrijven.

Hier is de foutregel:
perror(“ERROR schrijven naar socket”);
totale output:
ERROR schrijven naar socket: Slechte bestandsdescriptor

Ik weet zeker dat ik de verbinding tot stand heb gebracht, want PrepareResponseForConnectionTest werkt als een tierelier.

Kunt u enig idee hebben van de reden van de fout?

Toen ik gcc als compiler gebruikte, was er geen probleem. Daarna, vanwege het gebruik van meerdere nieuwe cpp-bronnen, gebruik ik g++ als compiler en heb ik deze fout.

Met vriendelijke groet

Hieronder mijn 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);  

}

Hieronder ziet u de code die foutloos wordt uitgevoerd:

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

Hier is mijn InitializeConnection-functie en ConnectToServer-functie:

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

Antwoord 1, autoriteit 100%

In het algemeen, wanneer “Slechte bestandsdescriptor” wordt aangetroffen, betekent dit dat de socketbestandsdescriptor die u aan de API hebt doorgegeven niet geldig is, wat meerdere mogelijke redenen heeft:

  1. De fd is al ergens gesloten.
  2. De fd heeft een verkeerde waarde, die niet overeenkomt met de waarde die is verkregen uit socket() api

Antwoord 2, autoriteit 31%

Ik had deze fout ook, mijn probleem zat in een deel van de code dat ik de bestandsdescriptor niet sloot en in een ander deel probeerde ik dat bestand te openen!!
gebruik close(fd)systeemaanroep nadat u klaar bent met werken een bestand.


Antwoord 3, autoriteit 31%

De waarde die u heeft doorgegeven als bestandsdescriptor is niet geldig. Het is ofwel negatief of vertegenwoordigt geen momenteel geopend bestand of socket.

Dus je hebt ofwel de socket gesloten voordat je write()aanroept, of je hebt de waarde van ‘sockfd’ ergens in je code beschadigd.

Het zou handig zijn om alle aanroepen te traceren naar close(), en de waarde van ‘sockfd’ voorafgaand aan de write()-aanroepen.

Uw techniek om alleen foutmeldingen af te drukken in debug-modus lijkt me complete waanzin, en in ieder geval is het aanroepen van een andere functie tussen een systeemaanroep en perror()ongeldig, omdat het de waarde kan verstoren van errno. In dit geval kan het inderdaad zo zijn geweest, en de echte onderliggende fout kan anders zijn.

Other episodes