1
votes

I am trying to send data / read data from socket fds with

write() and read() functions.

The problem is that one of them are not working correctly, I explain:

write() sends data to "sockfd" -> "sockfd" inserts data to "answer" variable with read() function

the problem is that when I try to get the content of answer (with the usual printf("%s\n",answer) ), it is empty.

I don't know if the problem comes from read() or write(), if both of them fail, they return -1 so I added a simple check to see if one of them return < 0.

Below the code:

This one is the sender, problem comes with the last write() call [This: if (write(client_sockfd,denied,sizeof(denied)) < 0)]

                                if(login_required(client_ipaddr) == 1)
                                {
                                  char getpasswd[256];
                                  char auth[256]="auth-required";
                                  char granted[9]="granted";
                                  char denied[7]="denied";
                                  //checks that password file exists!
                                  //check_passwd_file("passfile",client_sockfd);
                                  log_string("[CLIENT-AUTH]Authentication required! ...");
                                  write(client_sockfd,auth,sizeof(auth));
                                  read(client_sockfd,getpasswd,sizeof(getpasswd));
                                  //log_string(getpasswd);
                                  //check here
                                  if(strcmp(getpasswd,"jasmtest") == 0)
                                  {
                                    log_string("[PWD][OK]Password accepted!\n");
                                    log_string("[PWD][OK]Authorized!\n");
                                  }     
                                  else if(strcmp(getpasswd,"jasmtest") != 0)
                                  {
                                     log_error("[PWD][DEN]Wrong password!\n");
                                     log_error("[PWD][DEN]Closing connection...\n");
                                     if (write(client_sockfd,denied,sizeof(denied)) < 0)
                                       log_error("[core/ipc.c][start_server()][getpasswd][write()] ERROR while sending denied\n");
                                  }
                                }
                                else
                                {
                                  write(client_sockfd,not_required,sizeof(not_required));
                                  log_string("[CLIENT-AUTH]Authentication NOT required!");
                                }

Here is the "client" I explain: until write(sockfd,get_my_pass,sizeof(get_my_pass)); all is working, when i call: read(sockfd,answer,sizeof(answer)) it is not working anymore as I described above.

read(sockfd,get_msg_from_server,255);

        if(strcmp(get_msg_from_server, "auth-required") == 0)
        {
          printf("+-----------------------------------------------------------------------+\n");
          printf("* Authentication is required before accessing JASM Command Line Interface\n");
          printf("* Password: \n");

          write(sockfd,get_my_pass,sizeof(get_my_pass));
          if(read(sockfd,answer,sizeof(answer)) < 0)
           printf("* Error on read\n");

          if(strcmp(answer,"denied") == 0)
          {
              printf("* Non-authorized access!!\n");
              printf("* Exiting...\n");
              close(sockfd);
              exit(3);
          }

        }
        else if(strcmp(get_msg_from_server, "auth-not-required") == 0)
          printf("* Authentication is not required for this session\n");

Thanks to all of u :)

1
Do any of your reads and/or writes succeed? I noticed in the server portion of the code the first use of read and write fail to check the return value. Depending on how your socket connection was achieved, you could have some synchronous blocking issues as well.Erik
yes, previous write/read works on both of source codes :/Stefano Belli
But how do you know if you aren't checking the return value? Additionally, what is the value for errno when the one write you check returns with an error?Erik
Just because a read or write system call returns doesn't mean it succeeded. You need to check the return value every time to ensure that it succeeded and determine how many bytes were read or written. It's good programming practice. When those things fail, you should also capture the value of errno as an indication of why it failed. The perror function is a relatively simple way to get this information to begin with.Erik
Read the documentation closely, especially on what the functions return if they do not return -1.alk

1 Answers

2
votes

For the most part, you do not check the return values of your read() and write() calls. This is always an error if you are transferring more than one byte, for even if no I/O error occurs, these functions are in no way guaranteed to transfer the specified number of bytes. That number gives the maximum that will be transferred; you need to be prepared to transfer the desired bytes over multiple calls.

Moreover, it follows that in most cases you need some kind of protocol by which each reader can predict how many bytes to expect to read. If you're sending fixed-length messages then writer and reader must agree on message length; if you're sending variable-length messages then you need either a per-message explicit message length (itself a fixed-length component) or a message terminator that the reader can recognize.

Your case is somewhat illustrative. This write by the server:

write(client_sockfd,auth,sizeof(auth));

seems intended to be paired with this read by the client:

read(sockfd,get_msg_from_server,255);

Note, however, that auth is declared as char auth[256], so its size is 256. Supposing that the server indeed writes all 256 bytes (which as I said, is not guaranteed), the client reads at most 255 of them, leaving at least one waiting, unread. The next read (into answer) will start at that unread byte. It will be a 0 (given the initializer provided for auth), therefore answer will be interpreted an empty string, notwithstanding whatever bytes may follow that initial '\0'.

Indeed, even if the server successfully transfers fewer than 256 bytes, if it transfers even one more than enough for the client to recognize the message as containing the string "auth-required" then the next byte the client reads will always have value zero.