I'm in the making of a TCP client-server program that sends data from the server to the client (this works fine) and then echos it back to the server (doesn't work fine). when using the recv function, the first time I receive data works well but after that a lot of garbage comes in, the data itself comes as well but in the middle of a lot of garbage, both the recv/send return values are always correct. besides that the first time I start the testing of this program after starting the computer is much better (usually works). Does anyone have a idea about the why's? I believe some buffer fills up or the recv stops being a blocking function somehow...
Thanks in advance...
this is the Client's code:
for(i=0;i<FIRSTSENDING;i++)
//the buffer is a chained-list with 4 fields per struct ( x,y,z,time )
{
for(j=0;j<NUMBEROFVARIABLES;j++)
{
while(head->data[j][0]!='b'); //the data has a 'b' at first and 'e'
in the end.
b1 = send(t,head->data[j],strlen(head->data[j]),0);
}
while(head->general[0]!='b');
b1 = send(t,head->general,strlen(head->general),0);
temp = head;
head = head->next;
free(temp);
}
the code for the server is:
for(i=0;i<FIRSTSENDING;i++)
{
for(j=0;j<NUMBEROFVARIABLES;j++)
{
newDatagram->data[j][0]=0;
a = recv(s,reci, LENGTHVARAIBLE , 0);
strcpy(newDatagram->data[j],reci);
newDatagram->data[j][LENGTHVARAIBLE] = 0;
}
newDatagram->general[0]=0;
a = recv(s,reci, LENGTHTIME , 0);
strcpy(newDatagram->general,reci);
newDatagram->general[LENGTHTIME] = 0;
_ftime(&timebuffer);
//fixing the time and sending it
timer=(double)(timebuffer.millitm)/1000+timebuffer.time;
newDatagram->general[LENGTHTIME-1]=0;
pointerTime = &newDatagram->general[1];
if(newDatagram->general[0]=='b')
{
attol=std::stod(pointerTime);
if((timer-attol)>delay1)
delay1=timer-attol;
}
}
delay1=delay1/10*15*1000; //adding 10 percent and making milli the right delay
delay=(int)(delay1);
delay=delay% 100000;
nextDelay=delay;
printf("The first delay is: %d in milliseconds\n",delay); //This is an incriment of 10% to the delay.
the code finds the max delay for those runs and shows it.
a = recv(s,reci, LENGTHVARAIBLE , 0);
strcpy(newDatagram->data[j],reci);
This is not correct: strcpy expects the buffer to be a null-terminated string, but you do not send the terminating null byte. So strcpy reads more data from the buffer than recv fills in. Here is where the garbage comes from.
And even if you send the terminating null byte, you cannot guarantee that recv reads the whole message at once, or that it doesn't merge several messages in a single one (there are no any message boundaries in stream sockets).
You should use exactly a bytes after each recv (and maybe use memcpy instead of strcpy). To determine where a message ends, you can either send the zero byte and look for this byte at receiving side (note that you can get more than one message in a single recv call), or prepend each message with a fixed-length header containing the length of message.
Related
I'm building a multi-client<->server messaging application over TCP.
I created a non blocking server using epoll to multiplex linux file descriptors.
When a fd receives data, I read() /or/ recv() into buf.
I know that I need to either specify a data length* at the start of the transmission, or use a delimiter** at the end of the transmission to segregate the messages.
*using a data length:
char *buffer_ptr = buffer;
do {
switch (recvd_bytes = recv(new_socket, buffer_ptr, rem_bytes, 0)) {
case -1: return SOCKET_ERR;
case 0: return CLOSE_SOCKET;
default: break;
}
buffer_ptr += recvd_bytes;
rem_bytes -= recvd_bytes;
} while (rem_bytes != 0);
**using a delimiter:
void get_all_buf(int sock, std::string & inStr)
{
int n = 1, total = 0, found = 0;
char c;
char temp[1024*1024];
// Keep reading up to a '\n'
while (!found) {
n = recv(sock, &temp[total], sizeof(temp) - total - 1, 0);
if (n == -1) {
/* Error, check 'errno' for more details */
break;
}
total += n;
temp[total] = '\0';
found = (strchr(temp, '\n') != 0);
}
inStr = temp;
}
My question: Is it OK to loop over recv() until one of those conditions is met? What if a client sends a bogus message length or no delimiter or there is packet loss? Wont I be stuck looping recv() in my program forever?
Is it OK to loop over recv() until one of those conditions is met?
Probably not, at least not for production-quality code. As you suggested, the problem with looping until you get the full message is that it leaves your thread at the mercy of the client -- if a client decides to only send part of the message and then wait for a long time (or even forever) without sending the last part, then your thread will be blocked (or looping) indefinitely and unable to serve any other purpose -- usually not what you want.
What if a client sends a bogus message length
Then you're in trouble (although if you've chosen a maximum-message-size you can detect obviously bogus message-lengths that are larger than that size, and defend yourself by e.g. forcibly closing the connection)
or there is packet loss?
If there is a reasonably small amount of packet loss, the TCP layer will automatically retransmit the data, so your program won't notice the difference (other than the message officially "arriving" a bit later than it otherwise would have). If there is really bad packet loss (e.g. someone pulled the Ethernet cable out of the wall for 5 minutes), then the rest of the message might be delayed for several minutes or more (until connectivity recovers, or the TCP layer gives up and closes the TCP connection), trapping your thread in the loop.
So what is the industrial-grade, evil-client-and-awful-network-proof solution to this dilemma, so that your server can remain responsive to other clients even when a particular client is not behaving itself?
The answer is this: don't depend on receiving the entire message all at once. Instead, you need to set up a simple state-machine for each client, such that you can recv() as many (or as few) bytes from that client's TCP socket as it cares to send to you at any particular time, and save those bytes to a local (per-client) buffer that is associated with that client, and then go back to your normal event loop even though you haven't received the entire message yet. Keep careful track of how many valid received-bytes-of-data you currently have on-hand from each client, and after each recv() call has returned, check to see if the associated per-client incoming-data-buffer contains an entire message yet, or not -- if it does, parse the message, act on it, then remove it from the buffer. Lather, rinse, and repeat.
I got a snippet from internet for send data through a socket .
Here is the code .
u32_t nLength = 0;
u32_t nOffset = 0;
do {
nLength = nFullLength - nOffset;
status = Socket->Send(((u8_t*) buff) + nOffset, &nLength);
if (status != ERROR_SUCCESS) {
break;
}
nOffset += nLength;
} while (nOffset < nFullLength);
My doubts are :
When send(sock_fd, buf+bytes, buflen-bytes, flags); function running , it will send the entire data ?
Let's assume i have a buff with 45 byte length . So it will send like
send(buf+0, 45-0) = send(buf+0, 45);
So it will send complete data with length 45 ? what is the use of length here ? initially it will 45 . Isn't ?
Well, no. There's no guarantee that it will send all the data you ask it to send, that's why the code looks the way it does.
The manual page for send() states this pretty clearly:
Return Value
On success, these calls return the number of characters sent. On error, -1
is returned, and errno is set appropriately.
The same is true for e.g. a regular write() to a local file, by the way. It might never happen, but the way the interface is designed you're supposed to handle partial sends (and writes) if they do happen.
TCP is a streaming transport. There is no guarantee that a given send() operation will accept all of the bytes given to it at one time. It depends on the available kernel buffer space, the I/O mode of the socket (blocking vs non-blocking), etc. send() returns the number of bytes it actually accepted and put into the kernel buffer for subsequent transmission.
In the code example shown, it appears that Socket->Send() expects nLength to be initially set to the total number of bytes to sent, and it will then update nLength with the number of bytes actually sent. The code is adjusting its nOffset variable accordingly, looping just in case send() returns fewer bytes than requested, so it can call send() as many times as it takes to send the full number of bytes.
So, for example, lets assume the kernel accepts up to 20 bytes at a time. The loop would call send() 3 times:
send(buf+0, 45-0) // returns 20
send(buf+20, 45-20) // returns 20
send(buf+40, 45-40) // returns 5
// done
This is typical coding practice for TCP programming, given the streaming nature of TCP.
I have a problem about a server (call servera) that receive a file from another server end send it to the client. The problem is that client receive 0 as file size and so zero bytes of the file:
/* receive file size from serverB */
recv(s,&bytes,sizeof(bytes),0);
/* send file size to client */
send(file_descriptor,&bytes,sizeof(bytes),0);
bytes = ntohs(bytes);
/* receive (from serverb) and send immediately (to client)*/
while (total != bytes) {
nread = read(s,&c,sizeof(char));
if(nread == 1){
send(file_descriptor,&c,sizeof(c),0);
total += nread;
}
}
What's wrong?
Everything could be wrong.
You must check I/O calls for errors before relying on side-effects, otherwise you will get unpredictable results.
In your case, perhaps the first recv() fails, leaving bytes uninitialized at 0.
Also, the loop reading a single byte at a time is very inefficient, and still fails to check that it manages to send that byte (send() can fail in which case you need to re-try).
my question is can I receive a half message with the code below?
If I want to send a message like: "MESSAGE\n"
Can that happen I receive only M character if the channel is slowly?
and the code part:
fd.fd = c->socket;
fd.events = POLLIN;
bzero(received, sizeof(received));
result = poll(&fd, 1, time);
if(result > 0)
{
i = SSL_read ( (SSL *)c->sslHandle, (char*)received, INCOMING_BUFFERSIZE);
result = SSL_get_error(c->sslHandle, i);
...
}
Because I though I receive nothing until the the "\n" symbol is not received.
How can make sure I accept message only with \n at end of that.
thanks the help,
Tamas
EDIT: the version I am using is 1.0.1c
The socket is stream-based which means that you get a stream of bytes, not a message. Consequently with one recv() call you can get from 1 to all bytes of the data you've sent. You need to put the data to some intermediate buffer and analyze the buffer for some markers (\n in your case).
I have two programs that use socket programming to communicate. Initially I will specify the no. of hops as to how many time they have to exchange messages between each other. Each time it receives a message, it will append its id to it. Hence the string grows in size every time. My program is working fine for 8000 hops, but after it crosses 8000, although program p1 sends a string of length 16388, p2 identifies that there are only 16385 in the socket ready to be read. I use ioctl() to determine the amount of characters ready to recv() in the socket, and then recv it in a char * variable...
Is it because there is a delay in the send () in p1 and recv() in p2 , that p2 identifies only 16385 characters in the socket ?
For ex:
If P1 sends length(16388)
P2 receives only the following length(16385)
Say I'm trying to send you 8 pumpkins. I put 6 of them on the table. You think, "I'm expecting 8 pumpkins, not 6. I'll wait until he puts the last two on the table." I think, "I don't want too many pumpkins 'in flight' at once. I'll wait until he takes 2 of these 6 before I put the last 2 on the table." We're stuck. We're each waiting for the other. We'll wait forever.
You are not permitted to wait until more bytes are received before accepting the bytes that have already been received. The reason for this is simple: No network protocol can allow each side to wait for the other. Since TCP permits the sending side to wait in this context, it cannot permit the receiving side to wait as well.
So accept the bytes as they are received. Don't wait for the other side to send all of them before accepting any of them. Otherwise, what happens if the other side is waiting for you to accept the first one before it sends any more?
You're probably hitting a kernel buffer limit. You can probably increase SO_RCVBUF on the receiver and it will work as you expect: SIOCINQ will eventually return the full size of the unread data.
But you shouldn't do that to ensure proper Functioning. messing with buffers should only be done when you want to tweak performance.
You should restructure the code so that you never have to ask the kernel how many bytes are available. Just read up to a reasonable limit(like 4096) and deal with one application-level message being broken up in multiple pieces. If you need message lengths/boundaries then you MUST implement them yourself on top of TCP.
Here's some silly code to read a message with a length header:
int ret, len = 0, have_read;
have_read = 0;
while (have_read < sizeof(len)) {
// This will likely always return sizeof(len) the first time.
ret = read(fd, ((char*)&len) + have_read, sizeof(len) - have_read);
if (ret <= 0) {
// Handle error.
}
have_read += ret;
}
char* buf = malloc(len);
if (!buf) {
// Handle error.
}
have_read = 0;
while (have_read < len) {
ret = read(fd, buf + have_read, len - have_read);
if (ret <= 0) {
// Handle error.
}
have_read += ret;
}
// Handle message in buf.