i need to read an integer through a socket and the sens it to a function. i do
strcpy(out,"insert id messagge\n");
if (write(sd_client,out, sizeof(out))==-1){
printf("Error.\n");
}
while ((read(sd_client, &id, sizeof(int)))==-1){ //id is an integer
if(errno!=EINTR){
printf("Error.\n");
exit(-1);
}
}
messaggio2(sd_client, logi, atoi(id)); //atoi(id) try to send int to func
someone can help me please? :D
The second parameter of read and write is a pointer to the data.
When you say:
write(sd_client,out, sizeof(out))
you're passing the value of out. That should be:
write(sd_client, &out, sizeof(out))
Also, I think that you've declared id as int (which is correct), so why are you passing it to atoi? That function is for parsing a int from a string.
The problem you're having seems a bit vague since you haven't actually mentioned the errors you're getting, but from the code you have posted, it seems like you are running into two different problems:
atoi() is for converting a string value to an integer ... now it seems you already have an integer in the value of id, so the argument to atoi() is incorrect. You would simply need to use something like sprintf() or snprintf() to convert your integer value to a string value and then copy that into a user-defined string-buffer if you are wanting a string-representation of your integer.
You are working with sockets, therefore any information transferred over the network will be coming in network-byte-order. If you are on a little-endian platform, then the integer will be coming in a big-endian format, and you will be interpreting the value of your integer incorrect. Therefore you should be converting your integer to the native platform endian format using a function like ntohl() which can be found inside of the header file netinet/in.h
So for instance:
#include <netinet/in.h>
int id;
int sd_client;
//... code to open socket, etc.
//add your own error-checking ... stripped out here for simplicity's sake
read(sd_client, &id, sizeof(int));
id = ntohl(id);
char buffer[32];
snprintf(buffer, sizeof(buffer), "%d", id);
messaggio2(sd_client, logi, buffer);
Related
I have done the reading from a file and is stored as hex values(say the first value be D4 C3). This is then stored to a buffer of char datatype. But whenever i print the buffer i am getting a value likebuff[0]=ffffffD4; buff[1]=ffffffC3 and so on.
How can I store the actual value to the buffer without any added bytes?
Attaching the snippet along with this
ic= (char *)malloc(1);
temp = ic;
int i=0;
char buff[1000];
while ((c = fgetc(pFile)) != EOF)
{
printf("%x",c);
ic++;
buff[i]=c;
i++;
}
printf("\n\nNo. of bytes written: %d", i);
ic = temp;
int k;
printf("\nBuffer value is : ");
for(k=0;k<i;k++)
{
printf("%x",buff[k]);
}
The problem is a combination of two things:
First is that when you pass a smaller type to a variable argument function like printf it's converted to an int, which might include sign extension.
The second is that the format "%x" you are using expects the corresponding argument to be an unsigned int and treat it as such
If you want to print a hexadecimal character, then use the prefix hh, as in "%hhx".
See e.g. this printf (and family) reference for more information.
Finally, if you only want to treat the data you read as binary data, then you should consider using int8_t (or possibly uint8_t) for the buffer. On any platform with 8-bit char they are the same, but gives more information to the reader of the code (saying "this is binary data and not a string").
By default, char is signed on many platforms (standards doesn't dictate its signedness). When passing to variable argument list, standard expansions like char -> int are invoked. If char is unsigned, 0xd3 remains integer 0xd3. If char is signed, 0xd3 becomes 0xffffffd3 (for 32-bit integer) because this is the same integer value -45.
NB if you weren't aware of this, you should recheck the entire program, because such errors are very subtle. I've dealed once with a tool which properly worked only with forced -funsigned-char into make's CFLAGS. OTOH this flag, if available to you, could be a quick-and-dirty solution to this issue (but I suggest avoiding it for any longer appoaching).
The approach I'm constantly using is passing to printf()-like functions a value not c, but 0xff & c, it's visually easy to understand and stable for multiple versions. You can consider using hh modifier (UPD: as #JoachimPileborg have already suggested) but I'm unsure it's supported in all real C flavors, including MS and embedded ones. (MSDN doesn't list it at all.)
You did store the actual values in the buffer without the added bytes. You're just outputting the signed numbers with more digits. It's like you have "-1" in your buffer but you're outputting it as "-01". The value is the same, it's just you're choosing to sign extend it in the output code.
I am trying to write out the size in bytes of a string that is defined as
#define PATHA "/tmp/matrix_a"
using the code
rtn=write(data,(strlen(PATHA)*sizeof(char)),sizeof(int));
if(rtn < 0)
perror("Writing data_file 2 ");
I get back Writing data_file 2 : Bad address
What exactly about this is a bad address? The data file descriptor is open, and writes correctly immediately before and after the above code segment. The data to be written to the file data needs to be raw, and not ASCII.
I have also tried defining the string as a char[] with the same issue
The second argument to write() is the address of the bytes you want to write, but you are passing the bytes you want to write themselves. In order to get an address, you must store those bytes in a variable (you can't take the address of the result of an expression). For example:
size_t patha_len = strlen(PATHA);
rtn = write(data, &patha_len, sizeof patha_len);
The arguments to POSIX write() are:
#include <unistd.h>
ssize_t write(int fildes, const void *buf, size_t nbyte);
That's a:
file descriptor
buffer
size
You've passed two sizes instead of an address and a size.
Use:
rtn = write(data, PATHA, sizeof(PATHA)-1);
or:
rtn = write(data, PATHA, strlen(PATHA));
If you are seeking to write the size of the string as an int, then you need an int variable to pass to write(), like this:
int len = strlen(PATHA);
rtn = write(data, &len, sizeof(len));
Note that you can't just use a size_t variable unless you want to write a size_t; on 64-bit Unix systems, in particular, sizeof(size_t) != sizeof(int) in general, and you need to decide which size it is you want to write.
You also need to be aware that some systems are little-endian and others big-endian, and what you write using this mechanism on one type is not going to be readable on the other type (without mapping work done before or after I/O operations). You might choose to ignore this as a problem, or you might decide to use a portable format (usually, that's called 'network order', and is equivalent to big-endian), or you might decide to define that your code uses the opposite order. You can write the code so that the same logic is used on all platforms if you're careful (and all platforms get the same answers).
The second argument to write() is the buffer and third argument is the size:
ssize_t write(int fd, const void *buf, size_t count);
The posted code passes the length which is interpreted as an address which is incorrect. The compiler should have emitted a warning about this (don't ignore compiler warnings and compile with the warning level at the highest level).
Change to:
rtn=write(data, PATHA, strlen(PATHA));
Note sizeof(char) is guaranteed to be 1 so it can be omitted from the size calculation.
The Bad address error has already been answered. If you want to write the size of a string just use printf.
printf("Length: %d\n", strlen(data));
Either that, or you can write a function that will convert an integer to a string and print that out... I prefer printf :)
rtn = write(data, PATHA, strlen(PATHA));
is what you want I think. Arguments are supposed to be
file descriptor (data)
the source buffer (your string constant PATHA)
The number of bytes to pull from that buffer (measured using strlen() on the same PATHA constant)
Also, to be complete, you should always check rtn for how many characters you've written. You're not guaranteed that you write() all the bytes requested on all descriptor types. So sometimes you end up writing it in chunks, determined by the amount it answers that it wrote, vs how many you know you have yet to write still then.
Id just thought id ask this question to see whether it can actually be done.
if i want to store a number like "00000000000001", What would be the best way?
bearing in mind that this also has to be incrememted on a regular basis.
Im thinking either there is a way to do this with the integer or i have to convert to a char array somewhere along the line. This would be fine but its a pain to try and increment a string.
I would store it as an integer and only convert to the formatted version with leading zeros on demand when you need to produce output, for example with printf, sprintf etc.
It's far easier that way than storing a string and trying to perform arithmetic on strings. Not least because you have extra formatting requirements about your strings.
If for some reason it is awkward to store an integer as your master data do it like this.
Store the string as your master data.
Whenever you need to perform arithmetic, convert from string to integer.
When the arithmetic is complete, convert back to string and store.
You should simply store the number using an appropriate type (say, unsigned int), so that doing operations like 'increment by one' are easy - only bother worrying about leading zeros when displaying the number.
sprintf can actually do this for you:
unsigned int i = 1;
char buffer[64];
sprintf( buf, "%014u", i );
This prints '00000000000001'.
You could store it in a integer variable (provided there's an integer type that's wide enough for your needs). When printing, simply format the number to have the correct number of leading zeros.
#include <stdlib.h> // for itoa() call
#include <stdio.h> // for printf() call
int main() {
int num = 123;
char buf[5];
// convert 123 to string [buf]
itoa(num, buf, 10);
// print our string
printf("%s\n", buf);
return 0;
}
I want to know the method of converting an integer into char/string and vice-versa also.
I have already used sprintf(&charvar,"%d",&intvar) but it produces wrong output, possibly garbage.
i have also heard atoi() in gcc has bugs.Reference:GCC atoi bug
What is the other method to convert string/char back to int ?
Actually i want to send an integer from one machine to another using SOCK_STREAM .
//EDIT : I forgot to tell that sprintf() does conversion and returns positive value.
If you want to send an integer to another machine you can send it as binary data, just by sending the intvar directly to the stream, you don't have to convert it to a char first. That will only introduce problems with knowing the length of the data as different values generate different lengths of strings.
Please read the manual of 'sprintf' and 'sscanf', and maybe their safer versions are proper for you.
Remove the ampersand before intvar:
sprintf(&charvar,"%d",intvar)
Two notes:
Here, I assume that &charvar is of correct type, which it probably isn't.
Even though it might not make much difference here, it's a good to get into the habit of using snprintf in preference to sprintf.
Here's some example code:
int intvar = ...;
char str[16];
snprintf(str, sizeof(str), "%d", intvar);
You cannot sprintf to a variable. You need a buffer for it, because of possible several digits and the trailing zero. Moreover, the argument should be the int variable, not its address.
Example:
char buffer[256];
int i = 42;
sprintf(buffer, "%d", i);
(buffer will be filled with '4', '2' and trailing '\0').
your sprintf is wrong.You should write sprintf(string,"%d",integer);
If you want to send an integer over the network and thats why you want to convert it into string have a look at htons
with these functions you can convert an integer to network format and avoid different endianness problems!
If you just want to convert it to bytes you can do something like this:
char buf[4];
memcpy(buf,&integer,4);
If you want your string to have the value of the int then you should use sprintf.
I'm lead to believe that write() can only send data buffers of byte (i.e. signed char), so how do I send an array of long integers using the C write() function in the sys/socket.h library?
Obviously I can't just cast or convert long to char, as any numbers over 127 would be malformed.
I took a look at the question, how to decompose integer array to a byte array (pixel codings), but couldn't understand it - please could someone dumb it down a little if this is what I'm looking for?
Follow up question:
Why do I get weird results when reading an array of integers from a TCP socket?
the prototype for write is:
ssize_t write(int fd, const void *buf, size_t count);
so while it writes in units of bytes, it can take a pointer of any type. Passing an int* will be no problem at all.
EDIT:
I would however, recomend that you also send the amount of integers you plan to send first so the reciever knows how much to read. Something like this (error checking omitted for brevity):
int x[10] = { ... };
int count = 10;
write(sock, &count, sizeof(count));
write(sock, x, sizeof(x));
NOTE: if the array is from dynamic memory (like you malloced it), you cannot use sizeof on it. In this case count would be equal to: sizeof(int) * element_count
EDIT:
As Brian Mitchell noted, you will likely need to be careful of endian issues as well. This is the case when sending any multibyte value (as in the count I recommended as well as each element of the array). This is done with the: htons/htonl and ntohs/ntohl functions.
Write can do what you want it to, but there's some things to be aware of:
1: You may get a partial write that's not on an int boundary, so you have to be prepared to handle that situation
2: If the code needs to be portable, you should convert your array to a specific endianess, or encode the endianess in the message.
The simplest way to send a single int (assuming 4-byte ints) is :
int tmp = htonl(myInt);
write(socket, &tmp, 4);
where htonl is a function that converts the int to network byte order. (Similarly,. when you read from the socket, the function ntohl can be used to convert back to host byte order.)
For an array of ints, you would first want to send the count of array members as an int (in network byte order), then send the int values.
Yes, you can just cast a pointer to your buffer to a pointer to char, and call write() with that. Casting a pointer to a different type in C doesn't affect the contents of the memory being pointed to -- all it does is indicate the programmer's intention that the contents of memory at that address be interpreted in a different way.
Just make sure that you supply write() with the correct size in bytes of your array -- that would be the number of elements times sizeof (long) in your case.
It would be better to have serialize/de-serialize functionality in your client /server program.
Whenever you want to send data, serialize the data into a byte buffer and send it over TCP with byte count.
When receiving data, de-serialize the data from buffer to your own interpretation .
You can interpret byte buffer in any form as you like. It can contain basic data type, objects etc.
Just make sure to take care of endianess and also alignment stuff.
Declare a character array. In each location of the array, store integer numbers, not characters.
Then you just send that.
For example:
char tcp[100];
tcp[0] = 0;
tcp[1] = 0xA;
tcp[2] = 0xB;
tcp[3] = 0xC;
.
.
// Send the character array
write(sock, tcp, sizeof(tcp));
I think what you need to come up with here is a protocol.
Suppose your integer array is:
100, 99, 98, 97
Instead of writing the ints directly to the buffer, I would "serialize" the array by turning it into a string representation. The string might be:
"100,99,98,97"
That's what would be sent over the wire. On the receiving end, you'd split the string by the commas and build the array back up.
This is more standardised, is human readable, and means people don't have to think about hi/lo byte orders and other silly things.
// Sarcasm
If you were working in .NET or Java, you'd probably encode it in XML, like this:
<ArrayOfInt><Int>100</Int><Int>99</Int><Int>98</Int><Int>97</Int></ArrayOfInt>
:)