C Socket Write adding extra characters - c

I am trying to append " " to messages in a chat program. In the below example buf is a character array holding the message. The weird thing is when I send this down a socket with write() it sends it in 2 bursts. The first burst is the correct message, then a second burst is 2-3 random non alphabetic ascii characters. Any idea what is up? When I just send buf down the socket, it works correctly.
char nickmsg[550];
strcpy(nickmsg, "<");
strcat(nickmsg, username);
strcat(nickmsg, "> ");
strcat(nickmsg, buf);
write(sd, nickmsg, sizeof(nickmsg));

You don't want sizeof(nickmsg), you want strlen(nickmsg). Using sizeof(nickmsg), you're sending everything that's in that buffer, not just the string you built in it. If it's only the chars in the string you want to send, you need to calculate the length of what's in there. (btw, there are more efficient ways to create strings than repeated strcats)

You have this code:
char nickmsg[550];
strcpy(nickmsg, "<");
strcat(nickmsg, username);
strcat(nickmsg, "> ");
strcat(nickmsg, buf);
write(sd, nickmsg, sizeof(nickmsg));
This always sends 550 bytes, since sizeof(nickmsg) is 550. The end of the message will be marked by a zero-byte because nicknmsg is a C-style string.
If the receiver always grabs 550 bytes and ignores all bytes after the zero, this will work fine. You'll just be sending some junk bytes to the clients which might leak sensitive information.
The question is, what are you supposed to be sending? What is supposed to mark the end of the message?
Caution: Do not change sizeof(nickmsg) to strlen(nickmsg). That will leave the client no way at all to identify the end of the message. (Unless you are 100% positive the client does not need to identify the ends of messages.)

write() isn't sending extra characters, you are.
write(sd, nickmsg, sizeof(nickmsg));
Will send 500 characters (the size of your array). Since you didn't initialize all array elements to 0 you're getting whatever garbage is in memory past the data you inserted into it.
You want:
write(sd, nickmsg, strlen(nickmsg) + 1);

You are sending 500 bytes data, within which only first strlen(username)+3 has valid data. The rest is just the uninitialized data.

If you send it this way
write(sd, nickmsg, sizeof(nickmsg));
you are sending data equivalent to size of the buffer.Though your string may be valid c string ending with null character but still the client may not be treating strings that way.(If you are writing your own client program you may cover up in the client's program).

Related

Why does dynamically allocated array does not update with the new data coming?

I am trying to receive a message from the socket server which sends a large file of around 7MB. Thus in the following code, I try to concatenate all data into one array s from buffer. But as I try the following, I see that the length of s does not change at all, although the total bytes received continue to increase.
char buffer[300];
char* s = calloc(1, sizeof(char));
size_t n = 1;
while ((b_recv = recv(socket_fd,
buffer,
sizeof(buffer), 0)) > 0) {
char *temp = realloc(s, b_recv + n);
s = temp;
memcpy(s + n -1, buffer, b_recv);
n += b_recv;
s[n-1] = '\0';
printf("%s -- %zu",s, strlen(s));
}
free(s);
Is this not the correct way to update receive data of varying sizes? Also when I try to print s, it gives some random question mark characters. What is the mistake that I am making?
Why does dynamically allocated array does not update with the new data coming?
You have not presented any reason to believe that the behavior is as the question characterizes it. You are receiving binary data and storing it in memory, which is fine, but you cannot expect sensible results from treating such data as if it were a C string. Not even when you replace the last byte with a string terminator.
Binary data can and generally does contain bytes with value 0. C strings use such bytes as terminators marking the end of the string data, so, for example, strlen will measure only the number of bytes before the first zero byte, regardless of how many additional bytes have been stored after it. Moreover, even if you do not receive any zero bytes at all, your particular code inserts them, clobbering some of the real bytes received.
You may attempt to print such data to the console as if it were text, but if in fact it does not consist of text encoded according to the runtime character encoding then there is no reason to expect the resulting display to convey useful information. Instead, examine it in memory via a debugger, or write the raw bytes to a file and examine the result with a hex editor, or write them (still raw) through a filter that converts to hexadecimal or some other text representation, or similar. And you have as many bytes to examine as you have copied to the allocated space. You're keeping track of that already, so you don't need strlen() to tell you how many that is.

Printing a bitstream data /TCP related

I am trying to make a communication between a Client and a Sever through TCP.
Let's say the client send 10 Hex numbers as bitstream to Sever. send(socketID, pSend, 20, 0); Where pSend = &ArrayClient; and unsigned short ArrayClient[] = { 0A, 0B, BA, B1...., FA }.
The sever receive the bytes stream with recv(acceptID, pRecv, 20, 0). How can I print out the content in my pointer pRecv correctly. As Sever I won't know how many bytes did the Client send, therefore I don't know how many to print.
Because the datas were sent as bitstream, not a string. I can not know the end of the message by finding \0 like working with string.
So is there a way that I can know how many bytes that I received as sever, or any way to print out the bitstream in my pRecv as Hex numbers.
I have tried pointer to a pointer and something similar like this:
while( ((unsigned int*)pRecv)[i] != 0){
printf("%X", ((unsigned int*)pRecv)[i]);
i++;
}
When dealing with TCP, there is no built-in way of separating messages, so your protocol needs to delimit the message boundaries in some known way.
A simple way of doing this is by first sending single byte denoting the length of the message, then sending that number of bytes.
For example, before sending the above message, do this:
char mlen = 20;
send(socketID, &mlen, 1, 0);

Sending a null terminating character over a socket in c

I'm trying to send a string with a null terminating character inside of it to another connection.
Now I'm not dumb, I know a string will stop at that character, but is there any possible way to send a string to a socket like this, "Test\x00AFTERNULL\x00\r\n".
I was thinking maybe there's a way to convert it from one encoding to another or something. I'm not exactly smart in this area. Thanks for any help/input.
Sending over socket is not related to having null in middle of string or not, because send() will send a buffer with specific size.
This buffer can have any amount of zeroes in middle of it. You probably have used strlen() to get size of string and used it in send() which result in incorrect buffer length and missing some part of data.
You can do it like this for example (very simple one):
char buf[] = "Test\0AFTERNULL\0\r\n";
//'s' is socket descriptor
send(s, buf, sizeof(buf), 0);
Send and receive data via socket use byte array, not string.
Exampe: create array: {'T', 'E', 'S','T', 0, 'A'}, send this via socket with leng is 6. And the other socket will received same array

Read and write system calls returning gibberish (C)

Im writing 2 integers between a server and a client and it gets jumbled in between. The client writes:
char playerMove[3];
char oppMove[3];
write(sock, playerMove, 3);
printf("Waiting on Opponent's move.\n");
read(sock, oppMove, 3);
printf("this was Opponent's move: %s\n", oppMove);
while the relevant server code is
char playerMove[3];
read(socket1, playerMove, 3);
printf("First move is: %s", playerMove);
write(socket2, playerMove, 3);
the terminal shows that the client says
Waiting on Opponent's move.
this was Opponent's move: �D�K
but in the server's terminal I can clearly see that it went through properly
First move is: 3 1
Can someone help me out here? Im new to C. Do I need to do something special to write "3 1" to my client?
Try something like below. Here buffer oppMove is set to 0 before using it.
char playerMove[3];
char oppMove[3];
memset(oppMove,'\0',3);
write(sock, playerMove, 3);
printf("Waiting on Opponent's move.\n");
read(sock, oppMove, 3);
printf("this was Opponent's move: %s\n", oppMove);
I also suggest to use buffer of 4 byte long as pointed out by Sourav Ghosh
Your 3-element char array is too small to handle the string input of format "3 1". You need one more element to store the terminating null.
Also, in the client side, as per the code here, playerMove is used uninitalized. To avoid such cases, it's always adviced and a good practice to initalize the automatic local variables.
Read and write do not automatically append a NUL termination byte.
so do not expect them.
However there are a few problems with the code.
1) player move is not initialized, so trash is sent to the server.
2) the returned values from write and read should be checked
to assure the operations are successjul
3) the client call to printf is using '%s' which is expecting a
NUL terminated string, however the value read is just some
3 random characters (because the sent value was just some random characters.
suggestions:
1) initialize the player move array to some known value
2) in the printf() format string use '%c%c%c' Not '%s'
regarding the server code.
it is totally random the something printable was displayed on the terminal
especially since the value read (and the buffer read into)
is not NUL terminated.
the call to printf has the same problem with the format string
and needs the same fix as the client call to printf

sending data using send() function in linux

I read the documentation regarding send() function, when it was said that the third parameter (len) is "The length, in bytes, of the data in buffer pointed to by the buf parameter".
I can't seem to understand if it sends the number of bytes I pass, or I nedd to pass the size of the buffer and it sends all the data included there.
Exmaple:
#define X 256
// main :
char test[X] = {0};
memcpy(test, "hello", 6);
send(sockfd, test, 6, 0)
send(sockfd, test, 256,0)
// will the first opetion send only hello? or hello000000....?
Thanks!
The send function sends precisely the number of bytes you tell it to (assuming it's not interrupted and doesn't otherwise fail). The number of bytes you need to send is determined by the protocol you are implementing. For example, if the protocol says you should send "FOO\r\n", then you need to send 5 bytes. If the protocol specifies that integers are represented as 4 bytes in network byte order and you're sending an integer, the buffer should contain an integer in network byte order and you should send 4 bytes. The size of the buffer doesn't matter to send.
As a complement to David Schwartz proper answer:
Depending on if the socket is non-blocking,or not, it is NOT guaranteed that a single send will actually send all data. You must check return value and might have to call send again (with correct buffer offsets).
For instance if you want to send 10 bytes of data (len=10), you call send(sock, buf, len, 0). However lets say it only manages to send 5 bytes, then send(..) will return 5, meaning that you will have to call it again later like send(sock, (buf + 5), (len - 5), 0). Meaning, skip first five bytes in buffer, they're already sent, and withdraw five bytes from the total number of bytes (len) we want to send.
(Note that I used parenthesis to make it easier to read only, and it assumes that buf is a pointer to 1 byte type.)

Resources