I use this code to receive a String from a Java server in a C client.
if( recv( to_server_socket, &reply, sizeof( reply ), MSG_WAITALL ) != sizeof( reply ) )
{
printf( "socket read failed");
exit( -1 );
}
printf( "got reply: %d\n", ntohl( reply ) );
char buf[512];
ssize_t nbytes=0;
int byte_count;
byte_count = recv(to_server_socket, buf, sizeof buf, 0);
printf("recv()'d %d bytes of data in buf\n", byte_count);
buf[byte_count] = '\0';
printf("String : %s\n",buf);
For example, when the Java server sends this String
bZzrEcyVEmjmIf
I got this result
recv()'d 16 bytes of data in buf String :
so I received 16 bytes but the
printf("String : %s",buf);
don't show me anything.
The server sent this String
TYvuDbbKALp3scp
I tried this code
int i=0;
while(i<byte_count){
printf("String : %c\n",buf[i]);
i++; recv()'d 17 bytes of data in buf
and for result I have
String : String : String : String : T String : Y String : v String
: u String : D String : b String : b String : K String : A String : L
String : p String : 3 String : s String : c String : p
Are you sure your characters are printable?
Use something like this to see what you received:
for (int i = 0; i < byte_count; i++)
{
printf("%02x ", (unsigned int) buf[i]);
}
printf("\n"); // flush stdout
It appears that Java is sending a length-prefixed string. The first two bytes correspond to the length field. These two bytes determine how many bytes follow. Here's how I'd serialise and print that:
unsigned int str_len = buf[0] * 256 + buf[1];
char *str = buf + 2;
/* printf("%.*s\n", str_len, str); // You could use this,
instead of the following two lines: */
fwrite(str, 1, str_len, stdout);
putchar('\n');
A byte with the value 0 denotes the end of a string, in C. This explains why the string pointed to by buf appears to be empty. It also explains why any embedded characters in your length-prefixed string that have the value 0 will cause the commented out printf in my code to cease printing the string.
It's a character value that doesn't have a well-defined visual representation. This explains why embedded characters in your length-prefixed string will cause fwrite to print awkward-looking characters.
The string being sent contains 14 characters. If the C application receives 16 bytes for it, there are 2 extra bytes. Probably they are placed at the beginning of the buffer and note the length of the string being sent (this is how I would send strings over a TCP socket since message boundaries are not guaranteed to be kept there). And if the first byte is zero, you will surely see nothing.
Try printing out values of all the 16 bytes from the buf.
I would also advise to send and parse a length of the string before the actual characters and then read from the socked the appropriate (known) number of bytes, otherwise you risk to get an incomplete string or two concatenated strings.
The stdout stream is buffered, your printf should include \n to flush the stream
printf("String : %s\n",buf);
or
fflush(stdout);
struct _received_data
{
unsigned char len_byte1;
unsigned char len_byte2;
char *str;
} received_data;
Then, once your receive the buffer:
received_data *new_buf = (received_data*) buf;
printf( "String = %s", new_buf->str);
Note that the buffers that are used in send & recv are meant to carry binary data. If data being transmitted is a string, it needs to be managed (ie., adding '\0' and end of buffer etc). Also, in this case your Java server is adding length bytes following a protocol (which the client needs to be aware of).
Related
I'm currently working with processes, and encountered a problem while reading and writing char to a file.
The idea is we have couple of processes which should read an integer from file, increment it and write back. Here is my attempt: (i wont include error checking)
...
char n;
char buff[5];
int number;
...
read(my_desc, &n, 1);
number = (int)n;
number++;
sprintf(buff, "%4d", number);
write(my_desc, buff, sizeof(buff));
...
The file is just plain
0
But the output seems to be not correct (almost always garbage).
I already read write and read manuals but im clueless. I've checked some topics on read and write functions here on stack overflow, but most of them either don't work for me or i struggle with implementation.
Thanks in advance.
It appears that you are reading a single character, taking the ASCII code of that character and converting that number to a 4-character string, and then writing those 4 characters and the terminating null character back to the file.
According to the information that you provided in the comments section, this is not intended. If I understand you correctly, you rather want to
read the entire file as a string,
convert that string to a number,
increment that number,
convert that number back to a string and
overwrite the entire file with that string.
Step #1 can be accomplished with the function read. However, you should read in the whole file instead of only a single character.
Step #2 can be accomplished by using the function strtol.
Step #3 is trivial.
Step #4 can be accomplished using the function snprintf.
Step #5 can be accomplished by rewinding the file using the function lseek, and then using the function write.
I am assuming that the number represented in the file is in the respresentable range of a long int, which is -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807 on most POSIX platforms. This means that the length of the string can be up to 19 characters, 20 including the terminating null character. That is why I am using a buffer size of 20.
char buffer[20], *p;
ssize_t bytes_read;
long num;
bytes_read = read( my_desc, buffer, (sizeof buffer) - 1 );
if ( bytes_read <= 0 )
{
//TODO: handle input error
}
//add null terminating character to string
buffer[bytes_read] = '\0';
//attempt to convert the string to a number
num = strtol( buffer, &p, 10 );
//check for conversion error
if ( p == buffer )
{
//TODO: handle conversion error
}
//increment the number
num++;
//write incremented number to buffer
snprintf( buffer, sizeof buffer, "%ld", num );
//rewind file
lseek( my_desc, 0, SEEK_SET );
//write buffer to file
write( my_desc, buffer, strlen(buffer) );
Note that I have not tested this code.
Also note that this program assumes that the input file does not contain any leading zeros. If the file contains the text string "003", then this program will overwrite the first character with a 4, but leave the remaining characters in the file intact. If this is an issue, then you will have to add a call to ftruncate to truncate the file.
I'm trying to use sprintf() to put a string "inside itself", so I can change it to have an integer prefix. I was testing this on a character array of length 12 with "Hello World" inside it already.
The basic premise is that I want a prefix that denotes the amount of words within a string. So I copy 11 characters into a character array of length 12.
Then I try to put the integer followed by the string itself by using "%i%s" in the function. To get past the integer (I don't just use myStr as the argument for %s), I make sure to use myStr + snprintf(NULL, 0, "%i", wordCount), which should be myStr + characters taken up by the integer.
The problem is that I'm having is that it eats the 'H' when I do this and prints "2ello World" instead of having the '2' right beside the "Hello World"
So far I've tried different options for getting "past the integer" in the string when I try to copy it inside itself, but nothing really seems to be the right case, as it either comes out as an empty string or just the integer prefix itself '222222222222' copied throughout the entire array.
int main() {
char myStr[12];
strcpy(myStr, "Hello World");//11 Characters in length
int wordCount = 2;
//Put the integer wordCount followed by the string myStr (past whatever amount of characters the integer would take up) inside of myStr
sprintf(myStr, "%i%s", wordCount, myStr + snprintf(NULL, 0, "%i", wordCount));
printf("\nChanged myStr '%s'\n", myStr);//Prints '2ello World'
return 0;
}
First, to insert a one-digit prefix into a string “Hello World”, you need a buffer of 13 characters—one for the prefix, eleven for the characters in “Hello World”, and one for the terminating null character.
Second, you should not pass a buffer to snprintf as both the output buffer and an input string. Its behavior is not defined by the C standard when objects passed to it overlap.
Below is a program that shows you how to insert a prefix by moving the string with memmove. This is largely tutorial, as it is not generally a good way to manipulate strings. For short strings, where space is not an issue, most programmers would simply print the desired string into a temporary buffer, avoiding overlap issues.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Insert a decimal numeral for Prefix into the beginning of String.
Length specifies the total number of bytes available at String.
*/
static void InsertPrefix(char *String, size_t Length, int Prefix)
{
// Find out how many characters the numeral needs.
int CharactersNeeded = snprintf(NULL, 0, "%i", Prefix);
// Find the current string length.
size_t Current = strlen(String);
/* Test whether there is enough space for the prefix, the current string,
and the terminating null character.
*/
if (Length < CharactersNeeded + Current + 1)
{
fprintf(stderr,
"Error, not enough space in string to insert prefix.\n");
exit(EXIT_FAILURE);
}
// Move the string to make room for the prefix.
memmove(String + CharactersNeeded, String, Current + 1);
/* Remember the first character, because snprintf will overwrite it with a
null character.
*/
char Temporary = String[0];
// Write the prefix, including a terminating null character.
snprintf(String, CharactersNeeded + 1, "%i", Prefix);
// Restore the first character of the original string.
String[CharactersNeeded] = Temporary;
}
int main(void)
{
char MyString[13] = "Hello World";
InsertPrefix(MyString, sizeof MyString, 2);
printf("Result = \"%s\".\n", MyString);
}
The best way to deal with this is to create another buffer to output to, and then if you really need to copy back to the source string then copy it back once the new copy is created.
There are other ways to "optimise" this if you really needed to, like putting your source string into the middle of the buffer so you can append and change the string pointer for the source (not recommended, unless you are running on an embedded target with limited RAM and the buffer is huge). Remember code is for people to read so best to keep it clean and easy to read.
#define MAX_BUFFER_SIZE 128
int main() {
char srcString[MAX_BUFFER_SIZE];
char destString[MAX_BUFFER_SIZE];
strncpy(srcString, "Hello World", MAX_BUFFER_SIZE);
int wordCount = 2;
snprintf(destString, MAX_BUFFER_SIZE, "%i%s", wordCount, srcString);
printf("Changed string '%s'\n", destString);
// Or if you really want the string put back into srcString then:
strncpy(srcString, destString, MAX_BUFFER_SIZE);
printf("Changed string in source '%s'\n", srcString);
return 0;
}
Notes:
To be safer protecting overflows in memory you should use strncpy and snprintf.
I am trying to send a message with a check sum from an USB to serial port converter and back again.
But I can't make it work for some reason even tough I have tried for a hole day. I am starting to think that there is something wrong with the hardware but I thought that it would be a good idea to ask you guys before giving up... I am using cygwin for executing and compiling programs on a windows computer.
I would have liked to attach a picture of the terminal when the program is running but you have to have an reputation of >10 which I ain't :(. So I will have to describe it instead.....
I get the following information from the terminal when I try to send 'a'.
Enter a message: a
The checksum for your message to send is: 97
Your message to send is: a
a#
The checksum of the received message is: 97
The message wasn't properly received!
You received the following: a
a#
I receive what I send, but the check sum for 'a' should be 'a' right? So the string that should have been sent is "aa" instead of "a
a#" or am I completely lost here.
I have attached the relevant parts of the code below (printWhite() etc. change the color of the text and nothing more)
void main(){
regularSend();
regularReceive();
}
void regularSend(){
char buff2s[20];
unsigned char calculatedCS;
printf("Enter a message: ");
fgets(buff2s,15,stdin); // string input from keyboard
calculatedCS=checkSum(buff2s,strlen(buff2s));
printf("The checksum for your message to send is: %i\n",calculatedCS);
buff2s[strlen(buff2s)]=calculatedCS; //adds a checksum
buff2s[strlen(buff2s)]='\0'; //adds a new string terminator
printf("Your message to send is: %s\n",buff2s);
bytes_written=write(fd,buff2s,strlen(buff2s));
sleep(1);
}
void regularReceive(){
unsigned char buffR[20];
unsigned char rCS;
bytes_read=read(fd,buffR,sizeof(buffR)-1);
if(strlen(buffR)<1){
printRed();
printf(" No reply from the serial device! \n");
printWhite();
}
else{
rCS=checkSum(buffR,strlen(buffR)-2); //1 byte extra now
printf("The checksum of the received message is: %i\n", rCS);
true_or_false=check_checkSum(buffR,strlen(buffR)-1);
if(true_or_false==1){
buffR[strlen(buffR)-1]='\0'; //removes checksum
printf("Your message was: %s\n",buffR);
}
else{
printRed();
printf("The message wasn't properly received!\n");
printWhite();
printf("You received the following: %s\n\n",buffR);
}
}
}
unsigned char checkSum(char buff[], unsigned char nbrOfBytes){
unsigned char ic;
unsigned int t_cSum=0;
for (ic=0;ic<nbrOfBytes-1;ic++){
t_cSum=t_cSum+buff[ic];
}
return (unsigned char) t_cSum; //returns a 8bit checksum
}
unsigned char check_checkSum(char buffR_t[], unsigned char nbrOfBytes){ //<- check this
unsigned char r_cSum=checkSum(buffR_t,nbrOfBytes-1); //calculates the expected value of the checksum byte
if(r_cSum==(unsigned char)buffR_t[nbrOfBytes-2]){
printGreen();
printf("A message has been received! \n");
printWhite();
return 1;
}
else{
return 0;
}
}
Is someone able to spot my mistakes(I am almost sure that there is at least 2)? I would appreciate any help in this matter!
Best regards Henrik
As #Roddy pointed out, code is bad for it overwrites the string's \0 with the checksum, then tries to find the string length in the next line of a potentially unterminated string!
buff2s[strlen(buff2s)]=calculatedCS; //adds a checksum
buff2s[strlen(buff2s)]='\0'; //adds a new string terminator
Suggest:
size_t len = strlen(buff2s);
calculatedCS = checkSum(buff2s, len);
buff2s[len] = calculatedCS; //adds a checksum
buff2s[++len] = '\0'; //adds a new string terminator
bytes_written=write(fd, buff2s, len + 1);
Since working with strings, change checksum generator and checker to insure it does not create a '\0'.
unsigned char checkSum(char buff[], size_t nbrOfBytes){
size_t ic;
unsigned int t_cSum = 0;
for (ic=0; ic<nbrOfBytes-1; ic++){
t_cSum += buff[ic];
}
return (unsigned char) (t_cSum % 255 + 1);
}
RegularReceive() will not work. Suggest reading via fgetc() until a '\0' occurs. (or timeout or buffer full). In particular the following is dangerous as it is not known that buffR ends with a '\0' and the next function is strlen(buffR).
bytes_read = read(fd, buffR, sizeof(buffR)-1);
if(strlen(buffR)<1){
buff2s[strlen(buff2s)]=calculatedCS; //adds a checksum
buff2s[strlen(buff2s)]='\0'; //adds a new string terminator
Bad :-(
Just because your string has a null terminator doesn't mean it's nulls all the way beyond. Your first 'strlen' tells you where the current end is. You overwrite that with the checksum, but where the 'new terminator' goes could be anywhere. Do this instead.
int len = strlen(buff2s);
buff2s[len]=calculatedCS; //adds a checksum
buff2s[len+1]='\0'; //adds a new string terminator
(ideally, checking for buffer overflow as well...)
I'm trying to create a long string that is produced out of encrypted substrings. For the encryption I'm using AES128 and libmcrypt. The code is working, but I get a shorter output then I should and a beeping sound. I guess it's because I'm using strlen, but I have no idea, how I can avoid that. I will be very grateful for some suggestions. Here is my code:
char *Encrypt( char *key, char *message){
static char *Res;
MCRYPT mfd;
char *IV;
int i, blocks, key_size = 16, block_size = 16;
blocks = (int) (strlen(message) / block_size) + 1;
Res = calloc(1, (blocks * block_size));
mfd = mcrypt_module_open(MCRYPT_RIJNDAEL_128, NULL, "ecb", NULL);
mcrypt_generic_init(mfd, key, key_size, IV);
strncpy(Res, message, strlen(message));
mcrypt_generic(mfd, Res, block_size);
//printf("the encrypted %s\n", Res);
mcrypt_generic_deinit(mfd);
mcrypt_module_close(mfd);
return (Res);
}
char *mkline ( int cols) {
int j;
char seed[] = "thesecretmessage", key1[]="dontusethisinput", key2[]="abadinputforthis";
char *encrypted, *encrypted2, *in = malloc(cols * 16);
encrypted = Encrypt(key1, seed);
sprintf(in, "%s", encrypted);
encrypted2= Encrypt(key2, encrypted);
printf("encrypted2 before for-loop %s\n", encrypted2);
printf("encrypted2 before for loop len %d\n", strlen(encrypted2));
for (j=1; j<cols; j++) {
strcat(in, encrypted2);
memmove(encrypted2, Encrypt(key2, encrypted2),strlen(seed));
printf("encrypted2 %s on position %d\n" , encrypted2,j);
printf("encrypted2 len %d\n", strlen(encrypted2));
}
free(encrypted);
free(encrypted2);
return in;
}
int main(int argc, char *argv[]) {
char *line = mkline(15);
printf("line %s\n", line);
printf("line lenght %d\n", strlen(line));
return 0;
}
You get the beep sound because you are printing control character.
Also strlen return the size until the first '\0' character (because strings are zero terminated). That's why you get length less than you expect since the encrypted message may contain zeroes.
You can do something like this to return the result length:
char *Encrypt(const char *key, const char *message, int *result_len)
{
*result_len = blocks * block_size;
}
Also
memmove(encrypted2, Encrypt(key2, encrypted2),strlen(seed));
This line should produce a memory leak since every time you call Encrypt you call calloc (allocate new memory) which you need to free after you are done.
You probably should use memcpy, memmove is primarly used if there is a chance destination and source may overlap.
The encrypted string you are trying to print contains a stream of bytes where the value of the individual byte ranges from 0 to 255. Because you are using a cryptographically secure algorithm, the distribution of values is very close to even.
Since you are trying to print the encrypted string through a console, the console interprets some of the bytes as control characters (see Bell character) that are unprintable but have other effects instead, such as playing beeps.
Furthermore, strlen isn't doing what you think it should be doing because the encrypted string is not null-terminated, but instead contains zeroes amongst other bytes and they have no special meaning unlike in NULL terminated strings. You need to store the length of the string elsewhere.
Simple, you are treating binary output (any byte value) directly as printable text. Any character wit a code point below 32 (hex 20) isn't. E.g. the ASCII value for BELL (look it up) could be meaningful to you. Print the resulting bytes in hexadecimals and you should be ok.
I should like to add that in general it is good practice to clear any memory that held the plaintext/unencrypted message after you encrypt it if you can. This is not good coding practice, but good cryptology practice.
This can be done by:
memset(buffer, 0, length_of_buffer);
Don't worry, that won't be optimized out by your compiler. It's actually not smart enough to tell if you'll be using that area again or not.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the correct way of reading from a TCP socket in C/C++?
I'm trying to develop a TCP client/server. My problem is, when I try to send the data from cliente I do it in one sent.
But my problem appears when I try to receive the data with a specific structure, I mean, the first 8 bytes set a date, the next 10 a name, and undefined number of bytes set a text (this text ends with /r/n/r/n)
The client sends as follows:
char date[8];
char name[10];
char msg[4096];
strcpy(msg,"12/10/12"); //8 bytes
strcat(msg,"Kevin Fire"); //10 bytes
strcat(msg,"abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde\r\n\r\n");
nbytes_sent = send(sock,(char *)msg,sizeof(msg),0);
printf("Bytes_sent: %s -> %i\n",msg,nbytes_sent);
And the server try to parse the data from socket as follows:
char date[8];
char name[10];
char * text;
char buf[1024];
int i=0;
for(i=0; i < 8; i++)
date[i] = '\0';
for(i=0; i < 10; i++)
name[i] = '\0';
nbytes_read=recv(sclient,(char *)date,sizeof(date),0);
if(nbytes_read > 0){
printf("Date: %s (%i)\n",date,nbytes_read);
//cout.flush();
nbytes_read=recv(sclient,(char *)name,sizeof(name),0);
if(nbytes_read > 0){
printf("Name: %s (%i)\n",name,nbytes_read);
//cout.flush();
nbytes_read=recv(sclient,(char *)buf,sizeof(buf),0);
strcpy(text,buf);
while(nbytes_read > 0){
nbytes_read=recv(sclient(char*)buf,sizeof(buf),0);
strcat(text,buf);
}
}
}
printf("Date: %s. Name: %s. Text: %s\n",date,name,text);
Here's a simple "receive all" function:
int recv_all(int sockfd, void *buf, size_t len, int flags)
{
size_t toread = len;
char *bufptr = (char*) buf;
while (toread > 0)
{
ssize_t rsz = recv(sockfd, bufptr, toread, flags);
if (rsz <= 0)
return rsz; /* Error or other end closed cnnection */
toread -= rsz; /* Read less next time */
bufptr += rsz; /* Next buffer position to read into */
}
return len;
}
One (repeated) mistake is:
nbytes_read=recv(sclient,(char *)date,sizeof(date),0);
recv() does not null terminate. This means date will not have a null terminator if sizeof(date) bytes is read. This is a problem when a non-null terminated string is passed as an argument to printf() with "%s" format specifier. If the string is non-null terminated you may see garbage characters appearing after the actual string data. You need to read one less than the target buffer and null terminate or use the format specifier "%*.s" that does not require null termination:
printf("%.*s", n, s); /* Prints first 'n' bytes from 's'. */
Note you can initialise a char[] to all nulls instead of using a for:
char date[8] = "";
or you can use memset().
Adding to #hmjd's find:
declared at the var decls is your text pointer...
char * text;
then later...
strcpy(text,buf);
while(nbytes_read > 0){
nbytes_read=recv(sclient(char*)buf,sizeof(buf),0);
strcat(text,buf);
}
Maybe try setting that 'text' pointer to something beside a random stack value will help as well.
Continuing the barrage, though the following will not necessarily blow up, your date variable as:
char date[8];
on both client and server side The client variable isn't used at all. The server variable, however is:
nbytes_read=recv(sclient,(char *)date,sizeof(date),0);
if(nbytes_read > 0){
Problem is, the date you sent is, in fact, 8 chars wide already: "12/10/12". Therefore, even if you firm-up a null terminator on the end of your string, which you should always do regardless (good practice):
date[ sizeof(date)/sizeof(date[0])-1 ] = 0;
you'll be truncating off the last char of your date.
There are other things wrong with this; we've only pointed out a few. Think about sending length-prefixes with each of these data values in the array, with checks or range to ensure you get what you expected.
Finally, spending some time on the business-end of a debugger would probably do you very well, especially on the server side.