converting void* to char*

Ok, I don't know if any of you is familiar with the recv function, if you aren't please look it here:

http://www.opengroup.org/onlinepubs/009695399/functions/recv.html

There basically it puts the response from the server back into a void pointer , called buffer.. say that buffer is actually strings... so how would I print it out?
kuntilanakAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
Infinity08Connect With a Mentor Commented:
>> but in this case even after all data has been received the recv still blocks... that's my problem.

That's because you didn't follow all of my suggestions ;)

In short : you don't need to call recv any more if you have already received the data you needed ...
0
 
SreejithGCommented:
Cast it to  (char *)buffer
0
 
numberkruncherCommented:
The following method takes a buffer of a specified type and size where it will output data:

ssize_t recv(int socket, void *buffer, size_t length, int flags);

So if you know that this function is going to generate character data, then all you need to do is place that data within a character buffer.
int bufferSize = 1024;
char *myBuffer = new char[bufferSize];
 
if (recv(socket, myBuffer, 1024 * sizeof(char), flags) > 0)
{
     /* Display message when successful. */
     printf(myBuffer);
}

Open in new window

0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
ozoCommented:
if you mean a C null terminates string, you might use puts(biffer) or printf("%s",buffer)
otherwise, if it is not guarnateed to be null terminated, you might use
size= recv(socket, buffer, length, flags);
printf("%.*s",size,buffer)
0
 
kuntilanakAuthor Commented:
Before printing out the actual buffer that the server sent I tried to print out the quote_length, which is supposed to be the buffer size.. and it turns out when I print it out it's 0. Why is this? Am I doing it right?
recv(sock_fd, quote_received, quote_length,0);
printf("Quote length is %d\n", quote_length);

Open in new window

0
 
kuntilanakAuthor Commented:
and I don't know how big the buffer size sent by the server will be so I can't allocate
char *myBuffer = new char[bufferSize];

Open in new window

0
 
numberkruncherCommented:
You can use the MSG_PEEK flag to determine the size of the next message. So you can use the value returned by that to allocate your buffer.
0
 
kuntilanakAuthor Commented:
just to make it easier, I have attached my code below
cl.txt
0
 
SreejithGCommented:
length is in parameter.
Specifies the length in bytes of the buffer pointed to by the buffer argument.
should be like this
recv(sock_fd, quote_received, sizeof(quote_received),0);
0
 
ozoCommented:
if you pass recv a quote_length=0, you are telling it to receive no bytes
0
 
numberkruncherCommented:
If memory serves, you can do this like follows:
int quote_length = recv(sock_fd, quote_received, 0, MSG_PEEK);
 
char *myBuffer = new char[quote_length];
 
if (recv(sock_fd, quote_received, quote_length, 0) > 0)
{
     /* Display message when successful. */
     printf(myBuffer);
}

Open in new window

0
 
kuntilanakAuthor Commented:
I changed it to this and it still doesn't work
recv(sock_fd, quote_received, sizeof(quote_received),0);

Open in new window

0
 
kuntilanakAuthor Commented:
>>if you pass recv a quote_length=0, you are telling it to receive no bytes

I did not specify it to be 0 anywhere in the code, besides isn't the length determined by how much bytes the server send me
0
 
kuntilanakAuthor Commented:
I also tried to print out what recv returns and it returns -1 which should be fine...
0
 
SreejithGCommented:
In your code, you are not allocating memory for quote_received. Allocate memory and read
0
 
ozoCommented:

RETURN VALUES
     These calls return the number of bytes received, or -1 if an error
     occurred.
0
 
numberkruncherCommented:
As I said previously, you should be able to peek at the entry size with the following line. You can then use this value to allocate the memory you require.
/* First call to recv returns length of quote in bytes. */
int quote_length = recv(sock_fd, quote_received, 0, MSG_PEEK);
if (quote_length > 0)
{
     /* Allocate out buffer. */
     char *quote_recieved = new char[quote_length];
 
     /* Fetch data into buffer now that we know the size. */
     /* Verify that no errors were encountered. */
     if (recv(sock_fd, quote_received, quote_length, 0) > 0)
     {
          /* Display message when successful. */
          printf(quote_recieved);
     }
}

Open in new window

0
 
ozoCommented:
neither quote_received nor quote_length seem to have been initialzed
0
 
numberkruncherCommented:
Sorry, a slight typo in my previous post. The MSG_PEEK call of recv still needs a buffer to put data. So a small buffer is required to satisfy this call, most of the message data will be truncated, but will not be removed from the queue.

We can then use this value to allocate our actual quote buffer, and then actually get the information.

So amending this into the above code:
/* First call to recv returns length of quote in bytes. */
char temp_small_buffer[3];
int quote_length = recv(sock_fd, temp_small_buffer, 3, MSG_PEEK);
if (quote_length > 0)
{
     /* Allocate out buffer. */
     char *quote_recieved = new char[quote_length];
 
     /* Fetch data into buffer now that we know the size. */
     /* Verify that no errors were encountered. */
     if (recv(sock_fd, quote_received, quote_length, 0) > 0)
     {
          /* Display message when successful. */
          printf(quote_recieved);
     }
}
else if (quote_length < 0)
{
     /* A problem occurred whilst receiving data. */
     printf ("An error has occurred.");
}

Open in new window

0
 
kuntilanakAuthor Commented:
>>neither quote_received nor quote_length seem to have been initialzed

how do you do that?
0
 
kuntilanakAuthor Commented:
is there a way to fix this without using the MSG_PEEK
0
 
kuntilanakAuthor Commented:
ok I just initialized the quote_length and quote_received as below... just for test purpose.. however it still doesn't work...

when I tried to print the quote_received it prints nothing
int quote_length = 1024;
char *quote_received = malloc(quote_length);

Open in new window

0
 
kuntilanakAuthor Commented:
ok latest update:

for some reason when I do something like the code below it works and I have no idea why it is, can you guys tell me why this is??? is it because the server is sending two sent request back to the client so therefore I need two recv?
recv(sock_fd, quote_received, quote_length ,0);
printf("%s\n", quote_received);
recv(sock_fd, quote_received, quote_length ,0);
printf("%s\n", quote_received);

Open in new window

0
 
kuntilanakAuthor Commented:
I am able to pull out the data from the server now using the below code:

However, the server replied this at the end:

read_quote_num(19640): read error on quote number : Connection reset by peer

I have no idea why this is, can anyone have a guess at this?
recv(sock_fd, quote_size, 4 ,0);
quote_received = malloc(ntohl(*quote_size));
recv(sock_fd, quote_received, ntohl(*quote_size) ,0);
printf("%s\n", quote_received);

Open in new window

0
 
Infinity08Commented:
>> is it because the server is sending two sent request back to the client so therefore I need two recv?

Whether the server sends more than one request or not has no direct impact on how many recv's you need to do to get your data. The transport protocol streams the data to you, irrespective of the send's done on the sending side.

You need to do as many recv's as necessary to get the data you need. Always check the return value of recv to see how many (if any) bytes it returned. If you need more, then call recv again. If you have enough, no need to call recv again :)


>> read_quote_num(19640): read error on quote number : Connection reset by peer

"connection reset by peer" means that the other side closed the connection.
0
 
itsmeandnobodyelseCommented:
>>>> recv(sock_fd, quote_size, 4 ,0);
I wouldn't send and read each single attribut with a new call, especially if they are all of different type. That is too much error-prone and if you change one side you always have to change the other side too. You better send structures (with same alignment)  which build a full message. The last member of that structure could be of dynamic size though I rather would recommend to provide a very big char array at end which could hold any text size needed.

struct MyHeader
{
    unsigned int  quote_size;
    unsigned int  quote_received;
    unsigned int  message_type;
    unsigned int  message_length;
};
struct MyBuffer
{
     MyHeader  head;
     char  message[4080];
};

The sizeof(MyBuffer) should be 4096 on both sides.

You would send it like

   MyBuffer buf = { 0 };  // makes all zero
   buf.head.quote_size        = qs;
   buf.head.quote_received = qr;
   buf.head.quote_message_type = 1;  // say 1 is Normal_Text
   buf.head.quote_message_length = strlen(szmsg);
   strcpy(buf.head.message, szmsg);
   send(sock_fd, (char*)&buf, sizeof(buf.head) +
                                               buf.head.quote_message_length + 1, 1);


and receive it

    int rc = 0;
    int nread = 0;
    MyBuffer buf = { 0 };  // makes all zero
   
    // we have to read in a loop cause the buffer may be sent incomplete
    nread = 0;
    while (true)
    {
         rc = recv(sock_fd, ((char*)&buf)[nread], sizeof(buf)-nread, 0);
         if (rc == -1) // error
         {
               // handle error: get errno or call GetWSALastError on windows
         }
         nread += rc;
         if (nread >= (int)sizeof(buf.head) && 
             nread == sizeof(buf.head) + buf.head.message_length+1)
         {
                // coming here we have read all that was sent and break the loop
                break;
         }
         // read the rest nect cycle

     }
     
      // now the buf is filled and we could access the members e.g.
      printf("%s", buf.head.message);  
0
 
itsmeandnobodyelseCommented:
>>>> "connection reset by peer" means that the other side closed the connection.

That often happens if you have a console prog for send and the prog terminates before the client makes the read.

You should run the sender in a loop or at least ask for quit at end of prog.
0
 
kuntilanakAuthor Commented:
ok, then maybe I should use a while loop instead... the problem is that the first data sent back to the client is a 32 bit and the next one is I don't know what size it is... so how can I do this?
0
 
kuntilanakAuthor Commented:
I tried the while loop approach from my code below

however the program never quits, I never knew why.. although it seems like it's only printing the quote once...

can anyone help?
recv(sock_fd, quote_size, 4 ,0);
		quote_received = malloc(ntohl(*quote_size));
		while (recv(sock_fd, quote_received, ntohl(*quote_size) ,0) != 0)
			printf("%s\n", quote_received);
		close(sock_fd);

Open in new window

0
 
Infinity08Commented:
>> the problem is that the first data sent back to the client is a 32 bit and the next one is I don't know what size it is... so how can I do this?

As soon as you have received the 32bit value, you know the size of the rest of the data.
0
 
Infinity08Commented:
>> however the program never quits

1) you need to ALWAYS check the return value of recv. Also for the first call, to make sure that it actually received 4 bytes. Note that recv will return a negative value in certain cases - don't forget to check for that too. Check the reference page (you posted it in your question) for more information.

2) you're depending on the fact that the received data is null terminated. That isn't necessarily so.
0
 
Infinity08Commented:
What's the type of quote_size btw ?
0
 
kuntilanakAuthor Commented:
>>What's the type of quote_size btw ?

I declared this on top as I know the first byte sent from the server will be 32-bit integer in network byte-order.

int  quote_size[4];
0
 
Infinity08Commented:
You might want to make that an unsigned int type.
0
 
kuntilanakAuthor Commented:
and I think quote_size does the job right... as when I confirmed with the number of bytes that the server will send to the client, it matches it fine...

problem with my while loop above is that.. recv returns a 4 at the end and not a 0, I don't know where this 4 comes from.. my guess it's the 4 bytes that specifies how large the next buffer will be, but why is it sent at the end instead of the first time? If it is sent at the end then how come I can get the correct size of buffer when I do recv for the very first time? Can it be the case that the server sends the data backwards?
0
 
Infinity08Commented:
0
 
kuntilanakAuthor Commented:
i checked it and it returns 4 bytes which means it's a 32 bit
0
 
Infinity08Commented:
And the rest of that post ? Regarding recv returning a negative value and assuming null termination of the received data ?
0
 
kuntilanakAuthor Commented:
when I do something like this:

it works for some reason that I don't know why...
do {
			flag = recv(sock_fd, quote_received, ntohl(*quote_size) ,0);
			printf("%s\n", quote_received);
		} while (flag !=  ntohl(*quote_size) || flag != -1);

Open in new window

0
 
Infinity08Commented:
Euhm, that will loop infinitely. Are you sure that works ?

In any case, that's not what I was referring to.

With every call of recv you need to check the return value. If it's smaller than 0, then an error occurred, and you need to take appropriate action. If 0 is returned, then no data was received (if you need more data, just wait a bit and try again). If a value larger than 0 is returned, then that's the amount of bytes that was received (if you need more, then you need to call recv again to get the rest of the data).

Plus, as I said earlier : you cannot depend on the received data being null terminated, so specifically, you cannot use %s for it.
0
 
kuntilanakAuthor Commented:
so if I can't use %s then what should I do?
0
 
Infinity08Commented:
>> so if I can't use %s then what should I do?

First receive all the data you need, then add a null terminator, and then show it to the user. But you're skipping the most important part of my post ;)
0
 
kuntilanakAuthor Commented:
it's weird that now it doesn't work again and I don't know what i've changed...  here's what I did based on your suggestion
do {
                        flag = recv(sock_fd, quote_received, ntohl(*quote_size) ,0);
			   if (flag == -1 || flag == 0){
				close(sock_fd);
				exit(1);
			   }
                        printf("%s\n", quote_received);
                } while (flag > 0);
		free(quote_received);

Open in new window

0
 
Infinity08Commented:
>> it's weird that now it doesn't work again

Please re-read my suggestions. You've missed some important parts :)
0
 
kuntilanakAuthor Commented:
I did read your suggestion:

It's this part right?

With every call of recv you need to check the return value. If it's smaller than 0, then an error occurred, and you need to take appropriate action. If 0 is returned, then no data was received (if you need more data, just wait a bit and try again). If a value larger than 0 is returned, then that's the amount of bytes that was received (if you need more, then you need to call recv again to get the rest of the data).
0
 
Infinity08Commented:
If recv returns 0, it doesn't mean there was an error - it simply means that no data was available (yet). If you need more data, just wait, and try again.

And how about the parts where I speak about null termination ?

You might also want to show an error message in case recv returns -1 ... so you at least know what the problem was.
0
 
kuntilanakAuthor Commented:
>>you need more data, just wait, and try again.

how do you wait?
0
 
Infinity08Commented:
You could use the MSG_WAITALL flag (see the reference page you posted in your question), or you can actually call a system wait yourself ... Which one depends on your platform (Sleep, usleep, wait, ...).
0
 
Infinity08Commented:
At this point, I think it's more worthwhile for you to read up on socket programming before continuing. I suggest reading through this excellent tutorial ("Beej's Guide to Network Programming") :

        http://beej.us/guide/bgnet/
0
 
kuntilanakAuthor Commented:
ok.. I think that's beyond the scope of the course.. I think we can assume here that it will never wait..

also my implementation above works only if the quote sent is smaller or at least equal to quote_size, if it's bigger.. I don't know why it doesn't work
0
 
kuntilanakAuthor Commented:
I've read that as well before making this thread Infinity08
0
 
kuntilanakAuthor Commented:
anyway what you said was right, the code above goes through an infinite loop... it prints out the quotes I want perfectly, but it never goes out of that while loop...
0
 
Infinity08Commented:
>> ok.. I think that's beyond the scope of the course.. I think we can assume here that it will never wait..

If the course is about learning socket programming, then learning how to do it correctly is not beyond it's scope, I'd assume.


>> also my implementation above works only if the quote sent is smaller or at least equal to quote_size, if it's bigger.. I don't know why it doesn't work

Null termination ?
Multiple recv's to receive the whole data before showing it to the user ?
I think I already mentioned that ;)

Btw, you already know the size of the data to receive ... How is it possible that you receive more than that size ?
If the first 4 bytes tell you to receive x bytes, then call recv until you have received those x bytes, and stop there ...


>> I've read that as well before making this thread Infinity08

Maybe not in enough detail. That tutorial contains very clear code examples that show how to handle this kind of situation correctly.
0
 
kuntilanakAuthor Commented:
>>Btw, you already know the size of the data to receive ... How is it possible that you receive more than >>that size ?
>>If the first 4 bytes tell you to receive x bytes, then call recv until you have received those x bytes, and >>stop there ...

Yes that is right, that's why I am saying that we don't need a while loop here as we know how much the size of the data to receive after the first response from the server, therefore all we need to do is just do a recv command for the second time right...

however for a very large files.. this doesn't work.. I will need a while loop. The problem with my current while loop is that.. the loop is stuck when calling receive.. I think it calls receive but there's nothing to be received so therefore it's just sitting there like a dumb guy on a street and do nothing.. so somehow I need to fix this and after that it should run fine
0
 
Infinity08Commented:
>> Yes that is right, that's why I am saying that we don't need a while loop here as we know how much the size of the data to receive after the first response from the server, therefore all we need to do is just do a recv command for the second time right...

You DO need a while loop, since recv might not return all of the data immediately. You need to call recv 1 or more times until you have received all data.


>> The problem with my current while loop is that.. the loop is stuck when calling receive..

Are you using a blocking socket ? Is the data you need actually available ?
0
 
kuntilanakAuthor Commented:
>>Are you using a blocking socket ? Is the data you need actually available ?

I don't even know what a blocking socket is,below is my latest attempt
while (flag = recv(sock_fd, quote_received, ntohl(*quote_size), 0) > 0){
			if (flag == -1){
				perror("Error: Receiving message failed \n");
				close(sock_fd);
				exit(1);
			}
              	printf("%s\n", quote_received);
		} 

Open in new window

0
 
kuntilanakAuthor Commented:
the problem why receive won't go through is because of this:

If no messages are available at the socket and O_NONBLOCK is not set on the socket's file descriptor, recv() shall block until a message arrives

I didn't set O_NONBLOCK at the socket's file descriptor.. how can I set that? so that it won't block...
0
 
Infinity08Commented:
You often WANT it to block, and in this case it seems appropriate, because you know how much data you need to receive, so you just wait (block) until it's available.


>> I didn't set O_NONBLOCK at the socket's file descriptor.. how can I set that? so that it won't block...

http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking
0
 
kuntilanakAuthor Commented:
where should I put the:

fcntl(sock_fd, F_SETFL, O_NONBLOCK);

at?
0
 
kuntilanakAuthor Commented:
>>You often WANT it to block, and in this case it seems appropriate, because you know how much data >>you need to receive, so you just wait (block) until it's available.

but in this case even after all data has been received the recv still blocks... that's my problem.
0
 
kuntilanakAuthor Commented:
so are you saying we need some kind of counter that checks how much data have we received? if that counter has been reached then we close the socket and exit?
0
 
Infinity08Commented:
That would be a good start, yes :)
0
 
kuntilanakAuthor Commented:
>>That would be a good start, yes :)

thanks inifnity08 my code works now, I have a question about the recvfrom() function:

ssize_t recvfrom(int socket, void *buffer, size_t length, int flags,
             struct sockaddr *address, socklen_t *address_len

so if I don't need to send back to the server after I receive something from the server can I set struck sockaddress* address and socklen_t* address_len to 0?
0
 
Infinity08Commented:
recvfrom is only really useful for UDP or other connectionless protocols. For TCP, there's no need. Just stick with recv ;)
0
 
kuntilanakAuthor Commented:
yes.. I am trying to connect with UDP right now... :D that's why I am asking
0
 
Infinity08Commented:
We're getting far from the original question then ...

You can set that parameter to NULL if you don't need the sender address.
0
 
kuntilanakAuthor Commented:
we need the sender address (i.e server address here) if we want to send another message back to them right?
0
 
Infinity08Commented:
yes. Unless you already have it.
0
 
kuntilanakAuthor Commented:
and so I can set socklen_t *address_len to NULL as well.....?
0
 
Infinity08Commented:
Yes. How is this related to the original question ?
0
 
kuntilanakAuthor Commented:
nothing...it's quite off topic
0
All Courses

From novice to tech pro — start learning today.